From 3b9b6d0b8e7f798023c9d109c490449d528fde80 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:59:48 +0200 Subject: Adding upstream version 1:9.18.19. Signed-off-by: Daniel Baumann --- tests/isc/Makefile.am | 115 ++ tests/isc/Makefile.in | 1905 +++++++++++++++++++++++++++ tests/isc/aes_test.c | 232 ++++ tests/isc/buffer_test.c | 308 +++++ tests/isc/counter_test.c | 68 + tests/isc/crc64_test.c | 84 ++ tests/isc/doh_test.c | 2307 +++++++++++++++++++++++++++++++++ tests/isc/errno_test.c | 109 ++ tests/isc/file_test.c | 141 ++ tests/isc/hash_test.c | 96 ++ tests/isc/heap_test.c | 79 ++ tests/isc/hmac_test.c | 926 ++++++++++++++ tests/isc/ht_test.c | 322 +++++ tests/isc/lex_test.c | 355 ++++++ tests/isc/md_test.c | 555 ++++++++ tests/isc/mem_test.c | 521 ++++++++ tests/isc/netaddr_test.c | 145 +++ tests/isc/netmgr_test.c | 2897 ++++++++++++++++++++++++++++++++++++++++++ tests/isc/parse_test.c | 56 + tests/isc/pool_test.c | 153 +++ tests/isc/quota_test.c | 341 +++++ tests/isc/radix_test.c | 136 ++ tests/isc/random_test.c | 787 ++++++++++++ tests/isc/regex_test.c | 2335 ++++++++++++++++++++++++++++++++++ tests/isc/result_test.c | 64 + tests/isc/safe_test.c | 92 ++ tests/isc/siphash_test.c | 170 +++ tests/isc/sockaddr_test.c | 149 +++ tests/isc/stats_test.c | 104 ++ tests/isc/symtab_test.c | 135 ++ tests/isc/task_test.c | 1408 ++++++++++++++++++++ tests/isc/taskpool_test.c | 164 +++ tests/isc/testdata/file/keep | 0 tests/isc/time_test.c | 418 ++++++ tests/isc/timer_test.c | 599 +++++++++ tests/isc/uv_wrap.h | 327 +++++ 36 files changed, 18603 insertions(+) create mode 100644 tests/isc/Makefile.am create mode 100644 tests/isc/Makefile.in create mode 100644 tests/isc/aes_test.c create mode 100644 tests/isc/buffer_test.c create mode 100644 tests/isc/counter_test.c create mode 100644 tests/isc/crc64_test.c create mode 100644 tests/isc/doh_test.c create mode 100644 tests/isc/errno_test.c create mode 100644 tests/isc/file_test.c create mode 100644 tests/isc/hash_test.c create mode 100644 tests/isc/heap_test.c create mode 100644 tests/isc/hmac_test.c create mode 100644 tests/isc/ht_test.c create mode 100644 tests/isc/lex_test.c create mode 100644 tests/isc/md_test.c create mode 100644 tests/isc/mem_test.c create mode 100644 tests/isc/netaddr_test.c create mode 100644 tests/isc/netmgr_test.c create mode 100644 tests/isc/parse_test.c create mode 100644 tests/isc/pool_test.c create mode 100644 tests/isc/quota_test.c create mode 100644 tests/isc/radix_test.c create mode 100644 tests/isc/random_test.c create mode 100644 tests/isc/regex_test.c create mode 100644 tests/isc/result_test.c create mode 100644 tests/isc/safe_test.c create mode 100644 tests/isc/siphash_test.c create mode 100644 tests/isc/sockaddr_test.c create mode 100644 tests/isc/stats_test.c create mode 100644 tests/isc/symtab_test.c create mode 100644 tests/isc/task_test.c create mode 100644 tests/isc/taskpool_test.c create mode 100644 tests/isc/testdata/file/keep create mode 100644 tests/isc/time_test.c create mode 100644 tests/isc/timer_test.c create mode 100644 tests/isc/uv_wrap.h (limited to 'tests/isc') diff --git a/tests/isc/Makefile.am b/tests/isc/Makefile.am new file mode 100644 index 0000000..488ba50 --- /dev/null +++ b/tests/isc/Makefile.am @@ -0,0 +1,115 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBUV_LIBS) + +check_PROGRAMS = \ + aes_test \ + buffer_test \ + counter_test \ + crc64_test \ + errno_test \ + file_test \ + hash_test \ + heap_test \ + hmac_test \ + ht_test \ + lex_test \ + md_test \ + mem_test \ + netaddr_test \ + netmgr_test \ + parse_test \ + pool_test \ + quota_test \ + radix_test \ + random_test \ + regex_test \ + result_test \ + safe_test \ + siphash_test \ + sockaddr_test \ + stats_test \ + symtab_test \ + task_test \ + taskpool_test \ + time_test \ + timer_test + +if HAVE_LIBNGHTTP2 +check_PROGRAMS += \ + doh_test + +doh_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBNGHTTP2_CFLAGS) \ + $(OPENSSL_CFLAGS) + +doh_test_LDADD = \ + $(LDADD) \ + $(LIBNGHTTP2_LIBS) + +doh_test_SOURCES = \ + doh_test.c \ + uv_wrap.h + +endif HAVE_LIBNGHTTP2 + +hmac_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +hmac_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +md_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +md_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +netmgr_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_SOURCES = \ + netmgr_test.c \ + uv_wrap.h + +random_test_LDADD = \ + $(LDADD) \ + -lm + +task_test_CPPFLAGS = \ + $(AM_CPPFLAGS) + +task_test_LDADD = \ + $(LDADD) + +if HAVE_LIBXML2 +task_test_CPPFLAGS += $(LIBXML2_CFLAGS) +task_test_LDADD += $(LIBXML2_LIBS) +endif HAVE_LIBXML2 + +if HAVE_JSON_C +task_test_CPPFLAGS += $(JSON_C_CFLAGS) +task_test_LDADD += $(JSON_C_LIBS) +endif HAVE_JSON_C + + +EXTRA_DIST = testdata + +include $(top_srcdir)/Makefile.tests diff --git a/tests/isc/Makefile.in b/tests/isc/Makefile.in new file mode 100644 index 0000000..1060d23 --- /dev/null +++ b/tests/isc/Makefile.in @@ -0,0 +1,1905 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 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@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +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@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = aes_test$(EXEEXT) buffer_test$(EXEEXT) \ + counter_test$(EXEEXT) crc64_test$(EXEEXT) errno_test$(EXEEXT) \ + file_test$(EXEEXT) hash_test$(EXEEXT) heap_test$(EXEEXT) \ + hmac_test$(EXEEXT) ht_test$(EXEEXT) lex_test$(EXEEXT) \ + md_test$(EXEEXT) mem_test$(EXEEXT) netaddr_test$(EXEEXT) \ + netmgr_test$(EXEEXT) parse_test$(EXEEXT) pool_test$(EXEEXT) \ + quota_test$(EXEEXT) radix_test$(EXEEXT) random_test$(EXEEXT) \ + regex_test$(EXEEXT) result_test$(EXEEXT) safe_test$(EXEEXT) \ + siphash_test$(EXEEXT) sockaddr_test$(EXEEXT) \ + stats_test$(EXEEXT) symtab_test$(EXEEXT) task_test$(EXEEXT) \ + taskpool_test$(EXEEXT) time_test$(EXEEXT) timer_test$(EXEEXT) \ + $(am__EXEEXT_1) +@HAVE_LIBNGHTTP2_TRUE@am__append_2 = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test + +@HAVE_LIBXML2_TRUE@am__append_3 = $(LIBXML2_CFLAGS) +@HAVE_LIBXML2_TRUE@am__append_4 = $(LIBXML2_LIBS) +@HAVE_JSON_C_TRUE@am__append_5 = $(JSON_C_CFLAGS) +@HAVE_JSON_C_TRUE@am__append_6 = $(JSON_C_LIBS) +subdir = tests/isc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_LIBNGHTTP2_TRUE@am__EXEEXT_1 = doh_test$(EXEEXT) +aes_test_SOURCES = aes_test.c +aes_test_OBJECTS = aes_test.$(OBJEXT) +aes_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +aes_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +buffer_test_SOURCES = buffer_test.c +buffer_test_OBJECTS = buffer_test.$(OBJEXT) +buffer_test_LDADD = $(LDADD) +buffer_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +counter_test_SOURCES = counter_test.c +counter_test_OBJECTS = counter_test.$(OBJEXT) +counter_test_LDADD = $(LDADD) +counter_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +crc64_test_SOURCES = crc64_test.c +crc64_test_OBJECTS = crc64_test.$(OBJEXT) +crc64_test_LDADD = $(LDADD) +crc64_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +am__doh_test_SOURCES_DIST = doh_test.c uv_wrap.h +@HAVE_LIBNGHTTP2_TRUE@am_doh_test_OBJECTS = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test-doh_test.$(OBJEXT) +doh_test_OBJECTS = $(am_doh_test_OBJECTS) +am__DEPENDENCIES_2 = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +@HAVE_LIBNGHTTP2_TRUE@doh_test_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@HAVE_LIBNGHTTP2_TRUE@ $(am__DEPENDENCIES_1) +errno_test_SOURCES = errno_test.c +errno_test_OBJECTS = errno_test.$(OBJEXT) +errno_test_LDADD = $(LDADD) +errno_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +file_test_SOURCES = file_test.c +file_test_OBJECTS = file_test.$(OBJEXT) +file_test_LDADD = $(LDADD) +file_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +hash_test_SOURCES = hash_test.c +hash_test_OBJECTS = hash_test.$(OBJEXT) +hash_test_LDADD = $(LDADD) +hash_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +heap_test_SOURCES = heap_test.c +heap_test_OBJECTS = heap_test.$(OBJEXT) +heap_test_LDADD = $(LDADD) +heap_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +hmac_test_SOURCES = hmac_test.c +hmac_test_OBJECTS = hmac_test-hmac_test.$(OBJEXT) +hmac_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +ht_test_SOURCES = ht_test.c +ht_test_OBJECTS = ht_test.$(OBJEXT) +ht_test_LDADD = $(LDADD) +ht_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +lex_test_SOURCES = lex_test.c +lex_test_OBJECTS = lex_test.$(OBJEXT) +lex_test_LDADD = $(LDADD) +lex_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +md_test_SOURCES = md_test.c +md_test_OBJECTS = md_test-md_test.$(OBJEXT) +md_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +mem_test_SOURCES = mem_test.c +mem_test_OBJECTS = mem_test.$(OBJEXT) +mem_test_LDADD = $(LDADD) +mem_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +netaddr_test_SOURCES = netaddr_test.c +netaddr_test_OBJECTS = netaddr_test.$(OBJEXT) +netaddr_test_LDADD = $(LDADD) +netaddr_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +am_netmgr_test_OBJECTS = netmgr_test-netmgr_test.$(OBJEXT) +netmgr_test_OBJECTS = $(am_netmgr_test_OBJECTS) +netmgr_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +parse_test_SOURCES = parse_test.c +parse_test_OBJECTS = parse_test.$(OBJEXT) +parse_test_LDADD = $(LDADD) +parse_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +pool_test_SOURCES = pool_test.c +pool_test_OBJECTS = pool_test.$(OBJEXT) +pool_test_LDADD = $(LDADD) +pool_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +quota_test_SOURCES = quota_test.c +quota_test_OBJECTS = quota_test.$(OBJEXT) +quota_test_LDADD = $(LDADD) +quota_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +radix_test_SOURCES = radix_test.c +radix_test_OBJECTS = radix_test.$(OBJEXT) +radix_test_LDADD = $(LDADD) +radix_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +random_test_SOURCES = random_test.c +random_test_OBJECTS = random_test.$(OBJEXT) +random_test_DEPENDENCIES = $(am__DEPENDENCIES_2) +regex_test_SOURCES = regex_test.c +regex_test_OBJECTS = regex_test.$(OBJEXT) +regex_test_LDADD = $(LDADD) +regex_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +result_test_SOURCES = result_test.c +result_test_OBJECTS = result_test.$(OBJEXT) +result_test_LDADD = $(LDADD) +result_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +safe_test_SOURCES = safe_test.c +safe_test_OBJECTS = safe_test.$(OBJEXT) +safe_test_LDADD = $(LDADD) +safe_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +siphash_test_SOURCES = siphash_test.c +siphash_test_OBJECTS = siphash_test.$(OBJEXT) +siphash_test_LDADD = $(LDADD) +siphash_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +sockaddr_test_SOURCES = sockaddr_test.c +sockaddr_test_OBJECTS = sockaddr_test.$(OBJEXT) +sockaddr_test_LDADD = $(LDADD) +sockaddr_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +stats_test_SOURCES = stats_test.c +stats_test_OBJECTS = stats_test.$(OBJEXT) +stats_test_LDADD = $(LDADD) +stats_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +symtab_test_SOURCES = symtab_test.c +symtab_test_OBJECTS = symtab_test.$(OBJEXT) +symtab_test_LDADD = $(LDADD) +symtab_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +task_test_SOURCES = task_test.c +task_test_OBJECTS = task_test-task_test.$(OBJEXT) +@HAVE_LIBXML2_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@HAVE_JSON_C_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +task_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +taskpool_test_SOURCES = taskpool_test.c +taskpool_test_OBJECTS = taskpool_test.$(OBJEXT) +taskpool_test_LDADD = $(LDADD) +taskpool_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +time_test_SOURCES = time_test.c +time_test_OBJECTS = time_test.$(OBJEXT) +time_test_LDADD = $(LDADD) +time_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +timer_test_SOURCES = timer_test.c +timer_test_OBJECTS = timer_test.$(OBJEXT) +timer_test_LDADD = $(LDADD) +timer_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +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)/aes_test.Po \ + ./$(DEPDIR)/buffer_test.Po ./$(DEPDIR)/counter_test.Po \ + ./$(DEPDIR)/crc64_test.Po ./$(DEPDIR)/doh_test-doh_test.Po \ + ./$(DEPDIR)/errno_test.Po ./$(DEPDIR)/file_test.Po \ + ./$(DEPDIR)/hash_test.Po ./$(DEPDIR)/heap_test.Po \ + ./$(DEPDIR)/hmac_test-hmac_test.Po ./$(DEPDIR)/ht_test.Po \ + ./$(DEPDIR)/lex_test.Po ./$(DEPDIR)/md_test-md_test.Po \ + ./$(DEPDIR)/mem_test.Po ./$(DEPDIR)/netaddr_test.Po \ + ./$(DEPDIR)/netmgr_test-netmgr_test.Po \ + ./$(DEPDIR)/parse_test.Po ./$(DEPDIR)/pool_test.Po \ + ./$(DEPDIR)/quota_test.Po ./$(DEPDIR)/radix_test.Po \ + ./$(DEPDIR)/random_test.Po ./$(DEPDIR)/regex_test.Po \ + ./$(DEPDIR)/result_test.Po ./$(DEPDIR)/safe_test.Po \ + ./$(DEPDIR)/siphash_test.Po ./$(DEPDIR)/sockaddr_test.Po \ + ./$(DEPDIR)/stats_test.Po ./$(DEPDIR)/symtab_test.Po \ + ./$(DEPDIR)/task_test-task_test.Po \ + ./$(DEPDIR)/taskpool_test.Po ./$(DEPDIR)/time_test.Po \ + ./$(DEPDIR)/timer_test.Po +am__mv = mv -f +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 = aes_test.c buffer_test.c counter_test.c crc64_test.c \ + $(doh_test_SOURCES) errno_test.c file_test.c hash_test.c \ + heap_test.c hmac_test.c ht_test.c lex_test.c md_test.c \ + mem_test.c netaddr_test.c $(netmgr_test_SOURCES) parse_test.c \ + pool_test.c quota_test.c radix_test.c random_test.c \ + regex_test.c result_test.c safe_test.c siphash_test.c \ + sockaddr_test.c stats_test.c symtab_test.c task_test.c \ + taskpool_test.c time_test.c timer_test.c +DIST_SOURCES = aes_test.c buffer_test.c counter_test.c crc64_test.c \ + $(am__doh_test_SOURCES_DIST) errno_test.c file_test.c \ + hash_test.c heap_test.c hmac_test.c ht_test.c lex_test.c \ + md_test.c mem_test.c netaddr_test.c $(netmgr_test_SOURCES) \ + parse_test.c pool_test.c quota_test.c radix_test.c \ + random_test.c regex_test.c result_test.c safe_test.c \ + siphash_test.c sockaddr_test.c stats_test.c symtab_test.c \ + task_test.c taskpool_test.c time_test.c timer_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +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)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +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@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +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_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +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@ +ax_pthread_config = @ax_pthread_config@ +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 = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc $(CMOCKA_CFLAGS) \ + -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBUV_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +@HAVE_LIBNGHTTP2_TRUE@doh_test_CPPFLAGS = \ +@HAVE_LIBNGHTTP2_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_CFLAGS) \ +@HAVE_LIBNGHTTP2_TRUE@ $(OPENSSL_CFLAGS) + +@HAVE_LIBNGHTTP2_TRUE@doh_test_LDADD = \ +@HAVE_LIBNGHTTP2_TRUE@ $(LDADD) \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_LIBS) + +@HAVE_LIBNGHTTP2_TRUE@doh_test_SOURCES = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test.c \ +@HAVE_LIBNGHTTP2_TRUE@ uv_wrap.h + +hmac_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +hmac_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +md_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +md_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +netmgr_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_SOURCES = \ + netmgr_test.c \ + uv_wrap.h + +random_test_LDADD = \ + $(LDADD) \ + -lm + +task_test_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_3) $(am__append_5) +task_test_LDADD = $(LDADD) $(am__append_4) $(am__append_6) +EXTRA_DIST = testdata +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(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 tests/isc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/isc/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_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_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 + +aes_test$(EXEEXT): $(aes_test_OBJECTS) $(aes_test_DEPENDENCIES) $(EXTRA_aes_test_DEPENDENCIES) + @rm -f aes_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(aes_test_OBJECTS) $(aes_test_LDADD) $(LIBS) + +buffer_test$(EXEEXT): $(buffer_test_OBJECTS) $(buffer_test_DEPENDENCIES) $(EXTRA_buffer_test_DEPENDENCIES) + @rm -f buffer_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(buffer_test_OBJECTS) $(buffer_test_LDADD) $(LIBS) + +counter_test$(EXEEXT): $(counter_test_OBJECTS) $(counter_test_DEPENDENCIES) $(EXTRA_counter_test_DEPENDENCIES) + @rm -f counter_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(counter_test_OBJECTS) $(counter_test_LDADD) $(LIBS) + +crc64_test$(EXEEXT): $(crc64_test_OBJECTS) $(crc64_test_DEPENDENCIES) $(EXTRA_crc64_test_DEPENDENCIES) + @rm -f crc64_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(crc64_test_OBJECTS) $(crc64_test_LDADD) $(LIBS) + +doh_test$(EXEEXT): $(doh_test_OBJECTS) $(doh_test_DEPENDENCIES) $(EXTRA_doh_test_DEPENDENCIES) + @rm -f doh_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(doh_test_OBJECTS) $(doh_test_LDADD) $(LIBS) + +errno_test$(EXEEXT): $(errno_test_OBJECTS) $(errno_test_DEPENDENCIES) $(EXTRA_errno_test_DEPENDENCIES) + @rm -f errno_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(errno_test_OBJECTS) $(errno_test_LDADD) $(LIBS) + +file_test$(EXEEXT): $(file_test_OBJECTS) $(file_test_DEPENDENCIES) $(EXTRA_file_test_DEPENDENCIES) + @rm -f file_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(file_test_OBJECTS) $(file_test_LDADD) $(LIBS) + +hash_test$(EXEEXT): $(hash_test_OBJECTS) $(hash_test_DEPENDENCIES) $(EXTRA_hash_test_DEPENDENCIES) + @rm -f hash_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hash_test_OBJECTS) $(hash_test_LDADD) $(LIBS) + +heap_test$(EXEEXT): $(heap_test_OBJECTS) $(heap_test_DEPENDENCIES) $(EXTRA_heap_test_DEPENDENCIES) + @rm -f heap_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(heap_test_OBJECTS) $(heap_test_LDADD) $(LIBS) + +hmac_test$(EXEEXT): $(hmac_test_OBJECTS) $(hmac_test_DEPENDENCIES) $(EXTRA_hmac_test_DEPENDENCIES) + @rm -f hmac_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hmac_test_OBJECTS) $(hmac_test_LDADD) $(LIBS) + +ht_test$(EXEEXT): $(ht_test_OBJECTS) $(ht_test_DEPENDENCIES) $(EXTRA_ht_test_DEPENDENCIES) + @rm -f ht_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ht_test_OBJECTS) $(ht_test_LDADD) $(LIBS) + +lex_test$(EXEEXT): $(lex_test_OBJECTS) $(lex_test_DEPENDENCIES) $(EXTRA_lex_test_DEPENDENCIES) + @rm -f lex_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lex_test_OBJECTS) $(lex_test_LDADD) $(LIBS) + +md_test$(EXEEXT): $(md_test_OBJECTS) $(md_test_DEPENDENCIES) $(EXTRA_md_test_DEPENDENCIES) + @rm -f md_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(md_test_OBJECTS) $(md_test_LDADD) $(LIBS) + +mem_test$(EXEEXT): $(mem_test_OBJECTS) $(mem_test_DEPENDENCIES) $(EXTRA_mem_test_DEPENDENCIES) + @rm -f mem_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mem_test_OBJECTS) $(mem_test_LDADD) $(LIBS) + +netaddr_test$(EXEEXT): $(netaddr_test_OBJECTS) $(netaddr_test_DEPENDENCIES) $(EXTRA_netaddr_test_DEPENDENCIES) + @rm -f netaddr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(netaddr_test_OBJECTS) $(netaddr_test_LDADD) $(LIBS) + +netmgr_test$(EXEEXT): $(netmgr_test_OBJECTS) $(netmgr_test_DEPENDENCIES) $(EXTRA_netmgr_test_DEPENDENCIES) + @rm -f netmgr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(netmgr_test_OBJECTS) $(netmgr_test_LDADD) $(LIBS) + +parse_test$(EXEEXT): $(parse_test_OBJECTS) $(parse_test_DEPENDENCIES) $(EXTRA_parse_test_DEPENDENCIES) + @rm -f parse_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(parse_test_OBJECTS) $(parse_test_LDADD) $(LIBS) + +pool_test$(EXEEXT): $(pool_test_OBJECTS) $(pool_test_DEPENDENCIES) $(EXTRA_pool_test_DEPENDENCIES) + @rm -f pool_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pool_test_OBJECTS) $(pool_test_LDADD) $(LIBS) + +quota_test$(EXEEXT): $(quota_test_OBJECTS) $(quota_test_DEPENDENCIES) $(EXTRA_quota_test_DEPENDENCIES) + @rm -f quota_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(quota_test_OBJECTS) $(quota_test_LDADD) $(LIBS) + +radix_test$(EXEEXT): $(radix_test_OBJECTS) $(radix_test_DEPENDENCIES) $(EXTRA_radix_test_DEPENDENCIES) + @rm -f radix_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(radix_test_OBJECTS) $(radix_test_LDADD) $(LIBS) + +random_test$(EXEEXT): $(random_test_OBJECTS) $(random_test_DEPENDENCIES) $(EXTRA_random_test_DEPENDENCIES) + @rm -f random_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(random_test_OBJECTS) $(random_test_LDADD) $(LIBS) + +regex_test$(EXEEXT): $(regex_test_OBJECTS) $(regex_test_DEPENDENCIES) $(EXTRA_regex_test_DEPENDENCIES) + @rm -f regex_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(regex_test_OBJECTS) $(regex_test_LDADD) $(LIBS) + +result_test$(EXEEXT): $(result_test_OBJECTS) $(result_test_DEPENDENCIES) $(EXTRA_result_test_DEPENDENCIES) + @rm -f result_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(result_test_OBJECTS) $(result_test_LDADD) $(LIBS) + +safe_test$(EXEEXT): $(safe_test_OBJECTS) $(safe_test_DEPENDENCIES) $(EXTRA_safe_test_DEPENDENCIES) + @rm -f safe_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(safe_test_OBJECTS) $(safe_test_LDADD) $(LIBS) + +siphash_test$(EXEEXT): $(siphash_test_OBJECTS) $(siphash_test_DEPENDENCIES) $(EXTRA_siphash_test_DEPENDENCIES) + @rm -f siphash_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(siphash_test_OBJECTS) $(siphash_test_LDADD) $(LIBS) + +sockaddr_test$(EXEEXT): $(sockaddr_test_OBJECTS) $(sockaddr_test_DEPENDENCIES) $(EXTRA_sockaddr_test_DEPENDENCIES) + @rm -f sockaddr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sockaddr_test_OBJECTS) $(sockaddr_test_LDADD) $(LIBS) + +stats_test$(EXEEXT): $(stats_test_OBJECTS) $(stats_test_DEPENDENCIES) $(EXTRA_stats_test_DEPENDENCIES) + @rm -f stats_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stats_test_OBJECTS) $(stats_test_LDADD) $(LIBS) + +symtab_test$(EXEEXT): $(symtab_test_OBJECTS) $(symtab_test_DEPENDENCIES) $(EXTRA_symtab_test_DEPENDENCIES) + @rm -f symtab_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(symtab_test_OBJECTS) $(symtab_test_LDADD) $(LIBS) + +task_test$(EXEEXT): $(task_test_OBJECTS) $(task_test_DEPENDENCIES) $(EXTRA_task_test_DEPENDENCIES) + @rm -f task_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(task_test_OBJECTS) $(task_test_LDADD) $(LIBS) + +taskpool_test$(EXEEXT): $(taskpool_test_OBJECTS) $(taskpool_test_DEPENDENCIES) $(EXTRA_taskpool_test_DEPENDENCIES) + @rm -f taskpool_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(taskpool_test_OBJECTS) $(taskpool_test_LDADD) $(LIBS) + +time_test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES) $(EXTRA_time_test_DEPENDENCIES) + @rm -f time_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS) + +timer_test$(EXEEXT): $(timer_test_OBJECTS) $(timer_test_DEPENDENCIES) $(EXTRA_timer_test_DEPENDENCIES) + @rm -f timer_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(timer_test_OBJECTS) $(timer_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aes_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/counter_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc64_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doh_test-doh_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errno_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac_test-hmac_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ht_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md_test-md_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netaddr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netmgr_test-netmgr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quota_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radix_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/result_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/siphash_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockaddr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_test-task_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taskpool_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +doh_test-doh_test.o: doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT doh_test-doh_test.o -MD -MP -MF $(DEPDIR)/doh_test-doh_test.Tpo -c -o doh_test-doh_test.o `test -f 'doh_test.c' || echo '$(srcdir)/'`doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/doh_test-doh_test.Tpo $(DEPDIR)/doh_test-doh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh_test.c' object='doh_test-doh_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o doh_test-doh_test.o `test -f 'doh_test.c' || echo '$(srcdir)/'`doh_test.c + +doh_test-doh_test.obj: doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT doh_test-doh_test.obj -MD -MP -MF $(DEPDIR)/doh_test-doh_test.Tpo -c -o doh_test-doh_test.obj `if test -f 'doh_test.c'; then $(CYGPATH_W) 'doh_test.c'; else $(CYGPATH_W) '$(srcdir)/doh_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/doh_test-doh_test.Tpo $(DEPDIR)/doh_test-doh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh_test.c' object='doh_test-doh_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o doh_test-doh_test.obj `if test -f 'doh_test.c'; then $(CYGPATH_W) 'doh_test.c'; else $(CYGPATH_W) '$(srcdir)/doh_test.c'; fi` + +hmac_test-hmac_test.o: hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hmac_test-hmac_test.o -MD -MP -MF $(DEPDIR)/hmac_test-hmac_test.Tpo -c -o hmac_test-hmac_test.o `test -f 'hmac_test.c' || echo '$(srcdir)/'`hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmac_test-hmac_test.Tpo $(DEPDIR)/hmac_test-hmac_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac_test.c' object='hmac_test-hmac_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hmac_test-hmac_test.o `test -f 'hmac_test.c' || echo '$(srcdir)/'`hmac_test.c + +hmac_test-hmac_test.obj: hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hmac_test-hmac_test.obj -MD -MP -MF $(DEPDIR)/hmac_test-hmac_test.Tpo -c -o hmac_test-hmac_test.obj `if test -f 'hmac_test.c'; then $(CYGPATH_W) 'hmac_test.c'; else $(CYGPATH_W) '$(srcdir)/hmac_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmac_test-hmac_test.Tpo $(DEPDIR)/hmac_test-hmac_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac_test.c' object='hmac_test-hmac_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hmac_test-hmac_test.obj `if test -f 'hmac_test.c'; then $(CYGPATH_W) 'hmac_test.c'; else $(CYGPATH_W) '$(srcdir)/hmac_test.c'; fi` + +md_test-md_test.o: md_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md_test-md_test.o -MD -MP -MF $(DEPDIR)/md_test-md_test.Tpo -c -o md_test-md_test.o `test -f 'md_test.c' || echo '$(srcdir)/'`md_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md_test-md_test.Tpo $(DEPDIR)/md_test-md_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md_test.c' object='md_test-md_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md_test-md_test.o `test -f 'md_test.c' || echo '$(srcdir)/'`md_test.c + +md_test-md_test.obj: md_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md_test-md_test.obj -MD -MP -MF $(DEPDIR)/md_test-md_test.Tpo -c -o md_test-md_test.obj `if test -f 'md_test.c'; then $(CYGPATH_W) 'md_test.c'; else $(CYGPATH_W) '$(srcdir)/md_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md_test-md_test.Tpo $(DEPDIR)/md_test-md_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md_test.c' object='md_test-md_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md_test-md_test.obj `if test -f 'md_test.c'; then $(CYGPATH_W) 'md_test.c'; else $(CYGPATH_W) '$(srcdir)/md_test.c'; fi` + +netmgr_test-netmgr_test.o: netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netmgr_test-netmgr_test.o -MD -MP -MF $(DEPDIR)/netmgr_test-netmgr_test.Tpo -c -o netmgr_test-netmgr_test.o `test -f 'netmgr_test.c' || echo '$(srcdir)/'`netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netmgr_test-netmgr_test.Tpo $(DEPDIR)/netmgr_test-netmgr_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netmgr_test.c' object='netmgr_test-netmgr_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netmgr_test-netmgr_test.o `test -f 'netmgr_test.c' || echo '$(srcdir)/'`netmgr_test.c + +netmgr_test-netmgr_test.obj: netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netmgr_test-netmgr_test.obj -MD -MP -MF $(DEPDIR)/netmgr_test-netmgr_test.Tpo -c -o netmgr_test-netmgr_test.obj `if test -f 'netmgr_test.c'; then $(CYGPATH_W) 'netmgr_test.c'; else $(CYGPATH_W) '$(srcdir)/netmgr_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netmgr_test-netmgr_test.Tpo $(DEPDIR)/netmgr_test-netmgr_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netmgr_test.c' object='netmgr_test-netmgr_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netmgr_test-netmgr_test.obj `if test -f 'netmgr_test.c'; then $(CYGPATH_W) 'netmgr_test.c'; else $(CYGPATH_W) '$(srcdir)/netmgr_test.c'; fi` + +task_test-task_test.o: task_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_test-task_test.o -MD -MP -MF $(DEPDIR)/task_test-task_test.Tpo -c -o task_test-task_test.o `test -f 'task_test.c' || echo '$(srcdir)/'`task_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task_test-task_test.Tpo $(DEPDIR)/task_test-task_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='task_test.c' object='task_test-task_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_test-task_test.o `test -f 'task_test.c' || echo '$(srcdir)/'`task_test.c + +task_test-task_test.obj: task_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_test-task_test.obj -MD -MP -MF $(DEPDIR)/task_test-task_test.Tpo -c -o task_test-task_test.obj `if test -f 'task_test.c'; then $(CYGPATH_W) 'task_test.c'; else $(CYGPATH_W) '$(srcdir)/task_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task_test-task_test.Tpo $(DEPDIR)/task_test-task_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='task_test.c' object='task_test-task_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_test-task_test.obj `if test -f 'task_test.c'; then $(CYGPATH_W) 'task_test.c'; else $(CYGPATH_W) '$(srcdir)/task_test.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(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-am + +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-am + +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 + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +aes_test.log: aes_test$(EXEEXT) + @p='aes_test$(EXEEXT)'; \ + b='aes_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +buffer_test.log: buffer_test$(EXEEXT) + @p='buffer_test$(EXEEXT)'; \ + b='buffer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +counter_test.log: counter_test$(EXEEXT) + @p='counter_test$(EXEEXT)'; \ + b='counter_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +crc64_test.log: crc64_test$(EXEEXT) + @p='crc64_test$(EXEEXT)'; \ + b='crc64_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +errno_test.log: errno_test$(EXEEXT) + @p='errno_test$(EXEEXT)'; \ + b='errno_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +file_test.log: file_test$(EXEEXT) + @p='file_test$(EXEEXT)'; \ + b='file_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hash_test.log: hash_test$(EXEEXT) + @p='hash_test$(EXEEXT)'; \ + b='hash_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap_test.log: heap_test$(EXEEXT) + @p='heap_test$(EXEEXT)'; \ + b='heap_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hmac_test.log: hmac_test$(EXEEXT) + @p='hmac_test$(EXEEXT)'; \ + b='hmac_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ht_test.log: ht_test$(EXEEXT) + @p='ht_test$(EXEEXT)'; \ + b='ht_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +lex_test.log: lex_test$(EXEEXT) + @p='lex_test$(EXEEXT)'; \ + b='lex_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +md_test.log: md_test$(EXEEXT) + @p='md_test$(EXEEXT)'; \ + b='md_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +mem_test.log: mem_test$(EXEEXT) + @p='mem_test$(EXEEXT)'; \ + b='mem_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +netaddr_test.log: netaddr_test$(EXEEXT) + @p='netaddr_test$(EXEEXT)'; \ + b='netaddr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +netmgr_test.log: netmgr_test$(EXEEXT) + @p='netmgr_test$(EXEEXT)'; \ + b='netmgr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parse_test.log: parse_test$(EXEEXT) + @p='parse_test$(EXEEXT)'; \ + b='parse_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pool_test.log: pool_test$(EXEEXT) + @p='pool_test$(EXEEXT)'; \ + b='pool_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +quota_test.log: quota_test$(EXEEXT) + @p='quota_test$(EXEEXT)'; \ + b='quota_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +radix_test.log: radix_test$(EXEEXT) + @p='radix_test$(EXEEXT)'; \ + b='radix_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +random_test.log: random_test$(EXEEXT) + @p='random_test$(EXEEXT)'; \ + b='random_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +regex_test.log: regex_test$(EXEEXT) + @p='regex_test$(EXEEXT)'; \ + b='regex_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +result_test.log: result_test$(EXEEXT) + @p='result_test$(EXEEXT)'; \ + b='result_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +safe_test.log: safe_test$(EXEEXT) + @p='safe_test$(EXEEXT)'; \ + b='safe_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +siphash_test.log: siphash_test$(EXEEXT) + @p='siphash_test$(EXEEXT)'; \ + b='siphash_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sockaddr_test.log: sockaddr_test$(EXEEXT) + @p='sockaddr_test$(EXEEXT)'; \ + b='sockaddr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stats_test.log: stats_test$(EXEEXT) + @p='stats_test$(EXEEXT)'; \ + b='stats_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +symtab_test.log: symtab_test$(EXEEXT) + @p='symtab_test$(EXEEXT)'; \ + b='symtab_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +task_test.log: task_test$(EXEEXT) + @p='task_test$(EXEEXT)'; \ + b='task_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +taskpool_test.log: taskpool_test$(EXEEXT) + @p='taskpool_test$(EXEEXT)'; \ + b='taskpool_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +time_test.log: time_test$(EXEEXT) + @p='time_test$(EXEEXT)'; \ + b='time_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +timer_test.log: timer_test$(EXEEXT) + @p='timer_test$(EXEEXT)'; \ + b='timer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +doh_test.log: doh_test$(EXEEXT) + @p='doh_test$(EXEEXT)'; \ + b='doh_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +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 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +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: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/aes_test.Po + -rm -f ./$(DEPDIR)/buffer_test.Po + -rm -f ./$(DEPDIR)/counter_test.Po + -rm -f ./$(DEPDIR)/crc64_test.Po + -rm -f ./$(DEPDIR)/doh_test-doh_test.Po + -rm -f ./$(DEPDIR)/errno_test.Po + -rm -f ./$(DEPDIR)/file_test.Po + -rm -f ./$(DEPDIR)/hash_test.Po + -rm -f ./$(DEPDIR)/heap_test.Po + -rm -f ./$(DEPDIR)/hmac_test-hmac_test.Po + -rm -f ./$(DEPDIR)/ht_test.Po + -rm -f ./$(DEPDIR)/lex_test.Po + -rm -f ./$(DEPDIR)/md_test-md_test.Po + -rm -f ./$(DEPDIR)/mem_test.Po + -rm -f ./$(DEPDIR)/netaddr_test.Po + -rm -f ./$(DEPDIR)/netmgr_test-netmgr_test.Po + -rm -f ./$(DEPDIR)/parse_test.Po + -rm -f ./$(DEPDIR)/pool_test.Po + -rm -f ./$(DEPDIR)/quota_test.Po + -rm -f ./$(DEPDIR)/radix_test.Po + -rm -f ./$(DEPDIR)/random_test.Po + -rm -f ./$(DEPDIR)/regex_test.Po + -rm -f ./$(DEPDIR)/result_test.Po + -rm -f ./$(DEPDIR)/safe_test.Po + -rm -f ./$(DEPDIR)/siphash_test.Po + -rm -f ./$(DEPDIR)/sockaddr_test.Po + -rm -f ./$(DEPDIR)/stats_test.Po + -rm -f ./$(DEPDIR)/symtab_test.Po + -rm -f ./$(DEPDIR)/task_test-task_test.Po + -rm -f ./$(DEPDIR)/taskpool_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/timer_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/aes_test.Po + -rm -f ./$(DEPDIR)/buffer_test.Po + -rm -f ./$(DEPDIR)/counter_test.Po + -rm -f ./$(DEPDIR)/crc64_test.Po + -rm -f ./$(DEPDIR)/doh_test-doh_test.Po + -rm -f ./$(DEPDIR)/errno_test.Po + -rm -f ./$(DEPDIR)/file_test.Po + -rm -f ./$(DEPDIR)/hash_test.Po + -rm -f ./$(DEPDIR)/heap_test.Po + -rm -f ./$(DEPDIR)/hmac_test-hmac_test.Po + -rm -f ./$(DEPDIR)/ht_test.Po + -rm -f ./$(DEPDIR)/lex_test.Po + -rm -f ./$(DEPDIR)/md_test-md_test.Po + -rm -f ./$(DEPDIR)/mem_test.Po + -rm -f ./$(DEPDIR)/netaddr_test.Po + -rm -f ./$(DEPDIR)/netmgr_test-netmgr_test.Po + -rm -f ./$(DEPDIR)/parse_test.Po + -rm -f ./$(DEPDIR)/pool_test.Po + -rm -f ./$(DEPDIR)/quota_test.Po + -rm -f ./$(DEPDIR)/radix_test.Po + -rm -f ./$(DEPDIR)/random_test.Po + -rm -f ./$(DEPDIR)/regex_test.Po + -rm -f ./$(DEPDIR)/result_test.Po + -rm -f ./$(DEPDIR)/safe_test.Po + -rm -f ./$(DEPDIR)/siphash_test.Po + -rm -f ./$(DEPDIR)/sockaddr_test.Po + -rm -f ./$(DEPDIR)/stats_test.Po + -rm -f ./$(DEPDIR)/symtab_test.Po + -rm -f ./$(DEPDIR)/task_test-task_test.Po + -rm -f ./$(DEPDIR)/taskpool_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/timer_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local 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 \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# 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/tests/isc/aes_test.c b/tests/isc/aes_test.c new file mode 100644 index 0000000..9e9ea22 --- /dev/null +++ b/tests/isc/aes_test.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Test data from NIST KAT + */ + +isc_result_t +tohexstr(unsigned char *d, char *out); + +size_t +fromhexstr(const char *in, unsigned char *d); + +unsigned char plaintext[3 * ISC_AES_BLOCK_LENGTH]; +unsigned char ciphertext[ISC_AES_BLOCK_LENGTH]; +char str[2 * ISC_AES_BLOCK_LENGTH + 1]; +unsigned char key[ISC_AES256_KEYLENGTH + 1]; +size_t len; + +isc_result_t +tohexstr(unsigned char *d, char *out) { + isc_buffer_t b; + isc_region_t r; + + isc_buffer_init(&b, out, 2 * ISC_AES_BLOCK_LENGTH + 1); + r.base = d; + r.length = ISC_AES_BLOCK_LENGTH; + return (isc_hex_totext(&r, 0, "", &b)); +} + +size_t +fromhexstr(const char *in, unsigned char *d) { + isc_buffer_t b; + isc_result_t ret; + + isc_buffer_init(&b, d, ISC_AES256_KEYLENGTH + 1); + ret = isc_hex_decodestring(in, &b); + if (ret != ISC_R_SUCCESS) { + return (0); + } + return (isc_buffer_usedlength(&b)); +} + +typedef struct aes_testcase { + const char *key; + const char *input; + const char *result; +} aes_testcase_t; + +/* AES 128 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes128_test) { + aes_testcase_t testcases[] = { /* Test 1 (KAT ECBVarTxt128 #3) */ + { "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "96D9FD5CC4F07441727DF0F33E401A36" }, + /* Test 2 (KAT ECBVarTxt128 #123) */ + { "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "F9B0FDA0C4A898F5B9E6F661C4CE4D07" }, + /* Test 3 (KAT ECBVarKey128 #3) */ + { "F0000000000000000000000000000000", + "00000000000000000000000000000000", + "970014D634E2B7650777E8E84D03CCD8" }, + /* Test 4 (KAT ECBVarKey128 #123) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "41C78C135ED9E98C096640647265DA1E" }, + /* Test 5 (KAT ECBGFSbox128 #3) */ + { "00000000000000000000000000000000", + "6A118A874519E64E9963798A503F1D35", + "DC43BE40BE0E53712F7E2BF5CA707209" }, + /* Test 6 (KAT ECBKeySbox128 #3) */ + { "B6364AC4E1DE1E285EAF144A2415F7A0", + "00000000000000000000000000000000", + "5D9B05578FC944B3CF1CCF0E746CD581" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + UNUSED(state); + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES128_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes128_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +/* AES 192 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes192_test) { + aes_testcase_t testcases[] = { + /* Test 1 (KAT ECBVarTxt192 #3) */ + { "000000000000000000000000000000000000000000000000", + "F0000000000000000000000000000000", + "2A560364CE529EFC21788779568D5555" }, + /* Test 2 (KAT ECBVarTxt192 #123) */ + { "000000000000000000000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "2AABB999F43693175AF65C6C612C46FB" }, + /* Test 3 (KAT ECBVarKey192 #3) */ + { "F00000000000000000000000000000000000000000000000", + "00000000000000000000000000000000", + "180B09F267C45145DB2F826C2582D35C" }, + /* Test 4 (KAT ECBVarKey192 #187) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "EACF1E6C4224EFB38900B185AB1DFD42" }, + /* Test 5 (KAT ECBGFSbox192 #3) */ + { "000000000000000000000000000000000000000000000000", + "51719783D3185A535BD75ADC65071CE1", + "4F354592FF7C8847D2D0870CA9481B7C" }, + /* Test 6 (KAT ECBKeySbox192 #3) */ + { "CD62376D5EBB414917F0C78F05266433DC9192A1EC943300", + "00000000000000000000000000000000", + "7F6C25FF41858561BB62F36492E93C29" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES192_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes192_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +/* AES 256 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes256_test) { + aes_testcase_t testcases[] = { /* Test 1 (KAT ECBVarTxt256 #3) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "7F2C5ECE07A98D8BEE13C51177395FF7" }, + /* Test 2 (KAT ECBVarTxt256 #123) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "7240E524BC51D8C4D440B1BE55D1062C" }, + /* Test 3 (KAT ECBVarKey256 #3) */ + { "F0000000000000000000000000000000" + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "1C777679D50037C79491A94DA76A9A35" }, + /* Test 4 (KAT ECBVarKey256 #251) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "03720371A04962EAEA0A852E69972858" }, + /* Test 5 (KAT ECBGFSbox256 #3) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "8A560769D605868AD80D819BDBA03771", + "38F2C7AE10612415D27CA190D27DA8B4" }, + /* Test 6 (KAT ECBKeySbox256 #3) */ + { "984CA75F4EE8D706F46C2D98C0BF4A45" + "F5B00D791C2DFEB191B5ED8E420FD627", + "00000000000000000000000000000000", + "4307456A9E67813B452E15FA8FFFE398" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + UNUSED(state); + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES256_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes256_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_aes128_test) +ISC_TEST_ENTRY(isc_aes192_test) +ISC_TEST_ENTRY(isc_aes256_test) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/buffer_test.c b/tests/isc/buffer_test.c new file mode 100644 index 0000000..1c858d3 --- /dev/null +++ b/tests/isc/buffer_test.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* reserve space in dynamic buffers */ +ISC_RUN_TEST_IMPL(isc_buffer_reserve) { + isc_result_t result; + isc_buffer_t *b; + + UNUSED(state); + + b = NULL; + isc_buffer_allocate(mctx, &b, 1024); + assert_int_equal(b->length, 1024); + + /* + * 1024 bytes should already be available, so this call does + * nothing. + */ + result = isc_buffer_reserve(&b, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 1024); + + /* + * This call should grow it to 2048 bytes as only 1024 bytes are + * available in the buffer. + */ + result = isc_buffer_reserve(&b, 1025); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 2048); + + /* + * 2048 bytes should already be available, so this call does + * nothing. + */ + result = isc_buffer_reserve(&b, 2000); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 2048); + + /* + * This call should grow it to 4096 bytes as only 2048 bytes are + * available in the buffer. + */ + result = isc_buffer_reserve(&b, 3000); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 4096); + + /* Consume some of the buffer so we can run the next test. */ + isc_buffer_add(b, 4096); + + /* + * This call should fail and leave buffer untouched. + */ + result = isc_buffer_reserve(&b, UINT_MAX); + assert_int_equal(result, ISC_R_NOMEMORY); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 4096); + + isc_buffer_free(&b); +} + +/* dynamic buffer automatic reallocation */ +ISC_RUN_TEST_IMPL(isc_buffer_dynamic) { + isc_buffer_t *b; + size_t last_length = 10; + int i; + + UNUSED(state); + + b = NULL; + isc_buffer_allocate(mctx, &b, last_length); + assert_non_null(b); + assert_int_equal(b->length, last_length); + + isc_buffer_setautorealloc(b, true); + + isc_buffer_putuint8(b, 1); + + for (i = 0; i < 1000; i++) { + isc_buffer_putstr(b, "thisisa24charslongstring"); + } + assert_true(b->length - last_length >= 1000 * 24); + last_length += 1000 * 24; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint8(b, 1); + } + + assert_true(b->length - last_length >= 10000 * 1); + last_length += 10000 * 1; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint16(b, 1); + } + + assert_true(b->length - last_length >= 10000 * 2); + + last_length += 10000 * 2; + for (i = 0; i < 10000; i++) { + isc_buffer_putuint24(b, 1); + } + assert_true(b->length - last_length >= 10000 * 3); + + last_length += 10000 * 3; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint32(b, 1); + } + assert_true(b->length - last_length >= 10000 * 4); + + isc_buffer_free(&b); +} + +/* copy a region into a buffer */ +ISC_RUN_TEST_IMPL(isc_buffer_copyregion) { + unsigned char data[] = { 0x11, 0x22, 0x33, 0x44 }; + isc_buffer_t *b = NULL; + isc_result_t result; + + isc_region_t r = { + .base = data, + .length = sizeof(data), + }; + + UNUSED(state); + + isc_buffer_allocate(mctx, &b, sizeof(data)); + + /* + * Fill originally allocated buffer space. + */ + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Appending more data to the buffer should fail. + */ + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_NOSPACE); + + /* + * Enable auto reallocation and retry. Appending should now succeed. + */ + isc_buffer_setautorealloc(b, true); + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_free(&b); +} + +/* sprintf() into a buffer */ +ISC_RUN_TEST_IMPL(isc_buffer_printf) { + unsigned int used, prev_used; + const char *empty_fmt; + isc_result_t result; + isc_buffer_t *b, sb; + char buf[8]; + + UNUSED(state); + + /* + * Prepare a buffer with auto-reallocation enabled. + */ + b = NULL; + isc_buffer_allocate(mctx, &b, 0); + isc_buffer_setautorealloc(b, true); + + /* + * Sanity check. + */ + result = isc_buffer_printf(b, "foo"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(used, 3); + + result = isc_buffer_printf(b, "bar"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(used, 3 + 3); + + /* + * Also check the terminating NULL byte is there, even though it is not + * part of the buffer's used region. + */ + assert_memory_equal(isc_buffer_current(b), "foobar", 7); + + /* + * Skip over data from previous check to prevent failures in previous + * check from affecting this one. + */ + prev_used = used; + isc_buffer_forward(b, prev_used); + + /* + * Some standard usage checks. + */ + isc_buffer_printf(b, "%d", 42); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2); + + isc_buffer_printf(b, "baz%1X", 42); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2 + 5); + + isc_buffer_printf(b, "%6.1f", 42.42f); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2 + 5 + 6); + + /* + * Also check the terminating NULL byte is there, even though it is not + * part of the buffer's used region. + */ + assert_memory_equal(isc_buffer_current(b), "42baz2A 42.4", 14); + + /* + * Check an empty format string is properly handled. + * + * Note: we don't use a string literal for the format string to + * avoid triggering [-Werror=format-zero-length]. + * Note: we have a dummy third argument as some compilers complain + * without it. + */ + prev_used = used; + empty_fmt = ""; + result = isc_buffer_printf(b, empty_fmt, ""); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(prev_used, used); + + isc_buffer_free(&b); + + /* + * Check overflow on a static buffer. + */ + isc_buffer_init(&sb, buf, sizeof(buf)); + result = isc_buffer_printf(&sb, "123456"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "789"); + assert_int_equal(result, ISC_R_NOSPACE); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "78"); + assert_int_equal(result, ISC_R_NOSPACE); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "7"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 7); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_buffer_reserve) +ISC_TEST_ENTRY(isc_buffer_dynamic) +ISC_TEST_ENTRY(isc_buffer_copyregion) +ISC_TEST_ENTRY(isc_buffer_printf) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/counter_test.c b/tests/isc/counter_test.c new file mode 100644 index 0000000..dc8dc50 --- /dev/null +++ b/tests/isc/counter_test.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +/* test isc_counter object */ +ISC_RUN_TEST_IMPL(isc_counter) { + isc_result_t result; + isc_counter_t *counter = NULL; + int i; + + UNUSED(state); + + result = isc_counter_create(mctx, 0, &counter); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 10; i++) { + result = isc_counter_increment(counter); + assert_int_equal(result, ISC_R_SUCCESS); + } + + assert_int_equal(isc_counter_used(counter), 10); + + isc_counter_setlimit(counter, 15); + for (i = 0; i < 10; i++) { + result = isc_counter_increment(counter); + if (result != ISC_R_SUCCESS) { + break; + } + } + + assert_int_equal(isc_counter_used(counter), 15); + + isc_counter_detach(&counter); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_counter) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/crc64_test.c b/tests/isc/crc64_test.c new file mode 100644 index 0000000..cb96437 --- /dev/null +++ b/tests/isc/crc64_test.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +ISC_RUN_TEST_IMPL(isc_crc64_init) { + uint64_t crc; + + isc_crc64_init(&crc); + assert_int_equal(crc, 0xffffffffffffffffUL); +} + +static void +_crc64(const char *buf, size_t buflen, const char *result, const int repeats) { + uint64_t crc; + + isc_crc64_init(&crc); + assert_int_equal(crc, 0xffffffffffffffffUL); + + for (int i = 0; i < repeats; i++) { + isc_crc64_update(&crc, buf, buflen); + } + + isc_crc64_final(&crc); + + char hex[16 + 1]; + snprintf(hex, sizeof(hex), "%016" PRIX64, crc); + + assert_memory_equal(hex, result, (result ? strlen(result) : 0)); +} + +/* 64-bit cyclic redundancy check */ +ISC_RUN_TEST_IMPL(isc_crc64) { + _crc64(TEST_INPUT(""), "0000000000000000", 1); + _crc64(TEST_INPUT("a"), "CE73F427ACC0A99A", 1); + _crc64(TEST_INPUT("abc"), "048B813AF9F49702", 1); + _crc64(TEST_INPUT("message digest"), "5273F9EA7A357BF4", 1); + _crc64(TEST_INPUT("abcdefghijklmnopqrstuvwxyz"), "59F079F9218BAAA1", 1); + _crc64(TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789"), + "A36DA8F71E78B6FB", 1); + _crc64(TEST_INPUT("123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890"), + "81E5EB73C8E7874A", 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_crc64_init) +ISC_TEST_ENTRY(isc_crc64) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/doh_test.c b/tests/isc/doh_test.c new file mode 100644 index 0000000..090fb8f --- /dev/null +++ b/tests/isc/doh_test.c @@ -0,0 +1,2307 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#include "netmgr/http.c" +#include "netmgr/netmgr-int.h" +#include "netmgr/uv-compat.c" +#include "netmgr/uv-compat.h" +#include "netmgr_p.h" + +#include + +#define MAX_NM 2 + +static isc_sockaddr_t tcp_listen_addr; + +static uint64_t send_magic = 0; +static uint64_t stop_magic = 0; + +static uv_buf_t send_msg = { .base = (char *)&send_magic, + .len = sizeof(send_magic) }; + +static atomic_int_fast64_t active_cconnects = 0; +static atomic_int_fast64_t nsends = 0; +static atomic_int_fast64_t ssends = 0; +static atomic_int_fast64_t sreads = 0; +static atomic_int_fast64_t csends = 0; +static atomic_int_fast64_t creads = 0; +static atomic_int_fast64_t ctimeouts = 0; +static atomic_int_fast64_t total_sends = 0; + +static atomic_bool was_error = false; + +static bool reuse_supported = true; +static bool noanswer = false; + +static atomic_bool POST = true; + +static atomic_bool slowdown = false; + +static atomic_bool use_TLS = false; +static isc_tlsctx_t *server_tlsctx = NULL; +static isc_tlsctx_t *client_tlsctx = NULL; +static isc_tlsctx_client_session_cache_t *client_sess_cache = NULL; + +static isc_quota_t listener_quota; +static atomic_bool check_listener_quota = false; + +static isc_nm_http_endpoints_t *endpoints = NULL; + +static bool skip_long_tests = false; + +/* Timeout for soft-timeout tests (0.05 seconds) */ +#define T_SOFT 50 + +#define NSENDS 100 +#define NWRITES 10 + +#define CHECK_RANGE_FULL(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v >= atomic_load(&total_sends)); \ + } + +#define CHECK_RANGE_HALF(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v >= atomic_load(&total_sends) / 2); \ + } + +/* Enable this to print values while running tests */ +#undef PRINT_DEBUG +#ifdef PRINT_DEBUG +#define X(v) fprintf(stderr, #v " = %" PRIu64 "\n", atomic_load(&v)) +#else +#define X(v) +#endif + +#define SKIP_IN_CI \ + if (skip_long_tests) { \ + skip(); \ + return; \ + } + +typedef struct csdata { + isc_nm_recv_cb_t reply_cb; + void *cb_arg; + isc_region_t region; +} csdata_t; + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + csdata_t data; + + (void)atomic_fetch_sub(&active_cconnects, 1); + memmove(&data, arg, sizeof(data)); + isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data)); + if (result != ISC_R_SUCCESS) { + goto error; + } + + REQUIRE(VALID_NMHANDLE(handle)); + + result = isc__nm_http_request(handle, &data.region, data.reply_cb, + data.cb_arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); + return; +error: + data.reply_cb(handle, result, NULL, data.cb_arg); + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); + if (result == ISC_R_TOOMANYOPENFILES) { + atomic_store(&slowdown, true); + } else { + atomic_store(&was_error, true); + } +} + +static void +connect_send_request(isc_nm_t *mgr, const char *uri, bool post, + isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg, + bool tls, unsigned int timeout) { + isc_region_t copy; + csdata_t *data = NULL; + isc_tlsctx_t *ctx = NULL; + + copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length), + .length = region->length }; + memmove(copy.base, region->base, region->length); + data = isc_mem_get(mgr->mctx, sizeof(*data)); + *data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy }; + if (tls) { + ctx = client_tlsctx; + } + + isc_nm_httpconnect(mgr, NULL, &tcp_listen_addr, uri, post, + connect_send_cb, data, ctx, client_sess_cache, + timeout, 0); +} + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + isc_result_t result; + socklen_t addrlen = sizeof(*addr); + int fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + isc__nm_closesocket(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + isc__nm_closesocket(fd); + return (r); + } + + result = isc__nm_socket_reuse(fd); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + fprintf(stderr, + "setup_ephemeral_port: isc__nm_socket_reuse(): %s", + isc_result_totext(result)); + close(fd); + return (-1); + } + + result = isc__nm_socket_reuse_lb(fd); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + fprintf(stderr, + "setup_ephemeral_port: isc__nm_socket_reuse_lb(): %s", + isc_result_totext(result)); + close(fd); + return (-1); + } + if (result == ISC_R_NOTIMPLEMENTED) { + reuse_supported = false; + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + close(fd); + return (r); + } +#endif + + return (fd); +} + +/* Generic */ + +static void +noop_read_cb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, + void *cbarg) { + UNUSED(handle); + UNUSED(result); + UNUSED(region); + UNUSED(cbarg); +} + +thread_local uint8_t tcp_buffer_storage[4096]; +thread_local size_t tcp_buffer_length = 0; + +static int +setup_test(void **state) { + char *env_workers = getenv("ISC_TASK_WORKERS"); + size_t nworkers; + uv_os_sock_t tcp_listen_sock = -1; + isc_nm_t **nm = NULL; + + tcp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM); + if (tcp_listen_sock < 0) { + return (-1); + } + close(tcp_listen_sock); + tcp_listen_sock = -1; + + if (env_workers != NULL) { + workers = atoi(env_workers); + } else { + workers = isc_os_ncpus(); + } + INSIST(workers > 0); + nworkers = ISC_MAX(ISC_MIN(workers, 32), 1); + + if (!reuse_supported || getenv("CI") != NULL) { + skip_long_tests = true; + } + + atomic_store(&total_sends, NSENDS * NWRITES); + atomic_store(&nsends, atomic_load(&total_sends)); + + atomic_store(&csends, 0); + atomic_store(&creads, 0); + atomic_store(&sreads, 0); + atomic_store(&ssends, 0); + atomic_store(&ctimeouts, 0); + atomic_store(&active_cconnects, 0); + + atomic_store(&was_error, false); + + atomic_store(&POST, false); + atomic_store(&use_TLS, false); + + noanswer = false; + + isc_nonce_buf(&send_magic, sizeof(send_magic)); + isc_nonce_buf(&stop_magic, sizeof(stop_magic)); + if (send_magic == stop_magic) { + return (-1); + } + + nm = isc_mem_get(mctx, MAX_NM * sizeof(nm[0])); + for (size_t i = 0; i < MAX_NM; i++) { + isc__netmgr_create(mctx, nworkers, &nm[i]); + assert_non_null(nm[i]); + } + + server_tlsctx = NULL; + isc_tlsctx_createserver(NULL, NULL, &server_tlsctx); + isc_tlsctx_enable_http2server_alpn(server_tlsctx); + client_tlsctx = NULL; + isc_tlsctx_createclient(&client_tlsctx); + isc_tlsctx_enable_http2client_alpn(client_tlsctx); + isc_tlsctx_client_session_cache_create( + mctx, client_tlsctx, + ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, + &client_sess_cache); + + isc_quota_init(&listener_quota, 0); + atomic_store(&check_listener_quota, false); + + INSIST(endpoints == NULL); + endpoints = isc_nm_http_endpoints_new(mctx); + + *state = nm; + + return (0); +} + +static int +teardown_test(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + + for (size_t i = 0; i < MAX_NM; i++) { + isc__netmgr_destroy(&nm[i]); + assert_null(nm[i]); + } + isc_mem_put(mctx, nm, MAX_NM * sizeof(nm[0])); + + if (server_tlsctx != NULL) { + isc_tlsctx_free(&server_tlsctx); + } + if (client_tlsctx != NULL) { + isc_tlsctx_free(&client_tlsctx); + } + + isc_tlsctx_client_session_cache_detach(&client_sess_cache); + + isc_quota_destroy(&listener_quota); + + isc_nm_http_endpoints_detach(&endpoints); + + return (0); +} + +thread_local size_t nwrites = NWRITES; + +static void +sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf, + size_t outbuf_len, const char *append) { + isc_nm_http_makeuri(https, sa, NULL, 0, append, outbuf, outbuf_len); +} + +static isc_quota_t * +init_listener_quota(size_t nthreads) { + isc_quota_t *quotap = NULL; + if (atomic_load(&check_listener_quota)) { + unsigned max_quota = ISC_MAX(nthreads / 2, 1); + isc_quota_max(&listener_quota, max_quota); + quotap = &listener_quota; + } + return (quotap); +} + +static void +doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + assert_non_null(handle); + UNUSED(cbarg); + UNUSED(region); + + if (eresult == ISC_R_SUCCESS) { + (void)atomic_fetch_sub(&nsends, 1); + atomic_fetch_add(&csends, 1); + atomic_fetch_add(&creads, 1); + } else { + /* We failed to connect; try again */ + atomic_store(&was_error, true); + } +} + +static void +doh_reply_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(eresult); + UNUSED(cbarg); + + assert_non_null(handle); + + if (eresult == ISC_R_SUCCESS) { + atomic_fetch_add(&ssends, 1); + } +} + +static void +doh_receive_request_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + UNUSED(cbarg); + assert_non_null(handle); + + if (eresult != ISC_R_SUCCESS) { + atomic_store(&was_error, true); + return; + } + + atomic_fetch_add(&sreads, 1); + + memmove(tcp_buffer_storage + tcp_buffer_length, region->base, + region->length); + tcp_buffer_length += region->length; + + while (tcp_buffer_length >= sizeof(magic)) { + magic = *(uint64_t *)tcp_buffer_storage; + assert_true(magic == stop_magic || magic == send_magic); + + tcp_buffer_length -= sizeof(magic); + memmove(tcp_buffer_storage, tcp_buffer_storage + sizeof(magic), + tcp_buffer_length); + + if (magic == send_magic) { + if (!noanswer) { + isc_nm_send(handle, region, doh_reply_sent_cb, + NULL); + } + return; + } else if (magic == stop_magic) { + /* + * We are done, so we don't send anything back. + * There should be no more packets in the buffer. + */ + assert_int_equal(tcp_buffer_length, 0); + } + } +} + +ISC_RUN_TEST_IMPL(mock_doh_uv_tcp_bind) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +static void +doh_noop(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + + isc__netmgr_shutdown(connect_nm); + + assert_int_equal(0, atomic_load(&csends)); + assert_int_equal(0, atomic_load(&creads)); + assert_int_equal(0, atomic_load(&sreads)); + assert_int_equal(0, atomic_load(&ssends)); +} + +ISC_RUN_TEST_IMPL(doh_noop_POST) { + atomic_store(&POST, true); + doh_noop(state); +} + +ISC_RUN_TEST_IMPL(doh_noop_GET) { + atomic_store(&POST, false); + doh_noop(state); +} + +static void +doh_noresponse(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(doh_noresponse_POST) { + atomic_store(&POST, true); + doh_noresponse(state); +} + +ISC_RUN_TEST_IMPL(doh_noresponse_GET) { + atomic_store(&POST, false); + doh_noresponse(state); +} + +static void +timeout_query_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + UNUSED(eresult); + UNUSED(cbarg); + + assert_non_null(handle); + + if (eresult == ISC_R_SUCCESS) { + atomic_fetch_add(&csends, 1); + } + + isc_nmhandle_detach(&handle); +} + +static void +timeout_retry_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *arg) { + UNUSED(region); + UNUSED(arg); + + assert_non_null(handle); + + atomic_fetch_add(&ctimeouts, 1); + + if (eresult == ISC_R_TIMEDOUT && atomic_load(&ctimeouts) < 5) { + isc_nmhandle_settimeout(handle, T_SOFT); + return; + } + + isc_nmhandle_detach(&handle); +} + +static void +timeout_request_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isc_nmhandle_t *sendhandle = NULL; + isc_nmhandle_t *readhandle = NULL; + + REQUIRE(VALID_NMHANDLE(handle)); + + if (result != ISC_R_SUCCESS) { + goto error; + } + + isc_nmhandle_attach(handle, &sendhandle); + isc_nm_send(handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + timeout_query_sent_cb, arg); + + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, timeout_retry_cb, NULL); + return; + +error: + atomic_store(&was_error, true); +} + +static void +doh_timeout_recovery(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_tlsctx_t *ctx = atomic_load(&use_TLS) ? server_tlsctx : NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + + /* + * Shorten all the TCP client timeouts to 0.05 seconds. + * timeout_retry_cb() will give up after five timeouts. + */ + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url, + atomic_load(&POST), timeout_request_cb, NULL, ctx, + client_sess_cache, T_SOFT, 0); + + /* + * Sleep until sends reaches 5. + */ + for (size_t i = 0; i < 1000; i++) { + if (atomic_load(&ctimeouts) == 5) { + break; + } + isc_test_nap(1); + } + assert_true(atomic_load(&ctimeouts) == 5); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(doh_timeout_recovery_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_timeout_recovery(state); +} + +ISC_RUN_TEST_IMPL(doh_timeout_recovery_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_timeout_recovery(state); +} + +static void +doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + UNUSED(region); + + if (eresult != ISC_R_SUCCESS) { + atomic_store(&was_error, true); + return; + } + + assert_non_null(handle); + + int_fast64_t sends = atomic_fetch_sub(&nsends, 1); + atomic_fetch_add(&csends, 1); + atomic_fetch_add(&creads, 1); + if (sends > 0 && cbarg == NULL) { + size_t i; + for (i = 0; i < NWRITES / 2; i++) { + eresult = isc__nm_http_request( + handle, + &(isc_region_t){ + .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_send_reply_cb, (void *)1); + if (eresult == ISC_R_CANCELED) { + break; + } + assert_true(eresult == ISC_R_SUCCESS); + } + } +} + +static isc_threadresult_t +doh_connect_thread(isc_threadarg_t arg) { + isc_nm_t *connect_nm = (isc_nm_t *)arg; + char req_url[256]; + int64_t sends = atomic_load(&nsends); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + + while (sends > 0) { + /* + * We need to back off and slow down if we start getting + * errors, to prevent a thundering herd problem. + */ + int_fast64_t active = atomic_fetch_add(&active_cconnects, 1); + if (atomic_load(&slowdown) || active > workers) { + isc_test_nap(active - workers); + atomic_store(&slowdown, false); + } + connect_send_request( + connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS), + 30000); + sends = atomic_load(&nsends); + } + + return ((isc_threadresult_t)0); +} + +static void +doh_recv_one(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 1); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, NULL, atomic_load(&use_TLS), + 30000); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + while (atomic_load(&ssends) != 1 || atomic_load(&sreads) != 1 || + atomic_load(&csends) != 1) + { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + assert_int_equal(atomic_load(&csends), 1); + assert_int_equal(atomic_load(&creads), 1); + assert_int_equal(atomic_load(&sreads), 1); + assert_int_equal(atomic_load(&ssends), 1); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +static void +doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result, + void *arg) { + REQUIRE(VALID_NMHANDLE(handle)); + if (result != ISC_R_SUCCESS) { + goto error; + } + + result = isc__nm_http_request( + handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + + result = isc__nm_http_request( + handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + return; +error: + atomic_store(&was_error, true); +} + +static void +doh_recv_two(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_tlsctx_t *ctx = NULL; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + + if (atomic_load(&use_TLS)) { + ctx = client_tlsctx; + } + + isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url, + atomic_load(&POST), doh_connect_send_two_requests_cb, + NULL, ctx, client_sess_cache, 5000, 0); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + while (atomic_load(&ssends) != 2 || atomic_load(&sreads) != 2 || + atomic_load(&csends) != 2) + { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + assert_int_equal(atomic_load(&csends), 2); + assert_int_equal(atomic_load(&creads), 2); + assert_int_equal(atomic_load(&sreads), 2); + assert_int_equal(atomic_load(&ssends), 2); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +static void +doh_recv_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + /* wait for the all responses from the server */ + while (atomic_load(&ssends) < atomic_load(&total_sends)) { + if (atomic_load(&was_error)) { + break; + } + isc_test_nap(1); + } + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&use_TLS, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&use_TLS, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&use_TLS, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&use_TLS, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +static void +doh_recv_half_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc__netmgr_shutdown(connect_nm); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +static void +doh_half_recv_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +static void +doh_half_recv_half_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +/* See: GL #2858, !5319 */ +ISC_RUN_TEST_IMPL(doh_bad_connect_uri) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 1); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + server_tlsctx, endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * "https://::1:XXXX/dns-query" is a bad URI, it should be + * "https://[::1]:XXXX/dns-query" + */ + (void)snprintf(req_url, sizeof(req_url), "https://::1:%u/%s", + isc_sockaddr_getport(&tcp_listen_addr), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, NULL, true, 30000); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + /* As we used an ill-formed URI, there ought to be an error. */ + assert_true(atomic_load(&was_error)); + assert_int_equal(atomic_load(&csends), 0); + assert_int_equal(atomic_load(&creads), 0); + assert_int_equal(atomic_load(&sreads), 0); + assert_int_equal(atomic_load(&ssends), 0); +} + +ISC_RUN_TEST_IMPL(doh_parse_GET_query_string) { + UNUSED(state); + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "dns=AAABAAABAAAAAAAAAWE-" + "NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3" + "QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == strlen(str) - 4); + assert_true(memcmp(queryp, str + 4, len) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?dns=AAABAAABAAAAAAAAAWE-" + "NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3" + "QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == strlen(str) - 6); + assert_true(memcmp(queryp, str + 5, len) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123&dns=567"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "567", 3) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?name1=123&dns=567&name2=123&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "567", 3) == 0); + } + /* complex, but still valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%" + "BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%" + "D0%BD%D0%BD%D1%8F&dns=123&veaction=edit§ion=0"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "123", 3) == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%" + "BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%" + "D0%BD%D0%BD%D1%8F&veaction=edit§ion=0"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = ""; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123&&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%12&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 6); + assert_true(memcmp(queryp, "123%12", 6) == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%ZZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%%&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%AZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%0AZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 7); + assert_true(memcmp(queryp, "123%0AZ", 7) == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_base64url_to_base64) { + UNUSED(state); + char *res; + size_t res_len = 0; + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3U"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "PDw_Pz8-Pg"; + char res_test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "PDw_Pz8-Pg"; + char res_test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + NULL); + assert_non_null(res); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* invalid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, 0, &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = ""; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg=="; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the + end */ + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, NULL, 31231, &res_len); + assert_null(res); + assert_true(res_len == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_base64_to_base64url) { + char *res; + size_t res_len = 0; + UNUSED(state); + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3U="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "PDw_Pz8-Pg"; + char test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "PDw_Pz8-Pg"; + char test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + NULL); + assert_non_null(res); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* invalid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, 0, &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = ""; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg=="; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the + end */ + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, NULL, 31231, &res_len); + assert_null(res); + assert_true(res_len == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_path_validation) { + UNUSED(state); + + assert_true(isc_nm_http_path_isvalid("/")); + assert_true(isc_nm_http_path_isvalid(ISC_NM_HTTP_DEFAULT_PATH)); + assert_false(isc_nm_http_path_isvalid("laaaa")); + assert_false(isc_nm_http_path_isvalid("")); + assert_false(isc_nm_http_path_isvalid("//")); + assert_true(isc_nm_http_path_isvalid("/lala///")); + assert_true(isc_nm_http_path_isvalid("/lalaaaaaa")); + assert_true(isc_nm_http_path_isvalid("/lalaaa/la/la/la")); + assert_true(isc_nm_http_path_isvalid("/la/a")); + assert_true(isc_nm_http_path_isvalid("/la+la")); + assert_true(isc_nm_http_path_isvalid("/la&la/la*la/l-a_/la!/la\'")); + assert_true(isc_nm_http_path_isvalid("/la/(la)/la")); + assert_true(isc_nm_http_path_isvalid("/la,la,la")); + assert_true(isc_nm_http_path_isvalid("/la-'la'-la")); + assert_true(isc_nm_http_path_isvalid("/la:la=la")); + assert_true(isc_nm_http_path_isvalid("/l@l@l@")); + assert_false(isc_nm_http_path_isvalid("/#lala")); + assert_true(isc_nm_http_path_isvalid("/lala;la")); + assert_false( + isc_nm_http_path_isvalid("la&la/laalaala*lala/l-al_a/lal!/")); + assert_true(isc_nm_http_path_isvalid("/Lal/lAla.jpg")); + + /* had to replace ? with ! because it does not verify a query string */ + assert_true(isc_nm_http_path_isvalid("/watch!v=oavMtUWDBTM")); + assert_false(isc_nm_http_path_isvalid("/watch?v=dQw4w9WgXcQ")); + assert_true(isc_nm_http_path_isvalid("/datatracker.ietf.org/doc/html/" + "rfc2616")); + assert_true(isc_nm_http_path_isvalid("/doc/html/rfc8484")); + assert_true(isc_nm_http_path_isvalid("/123")); +} + +ISC_RUN_TEST_IMPL(doh_connect_makeuri) { + struct in_addr localhostv4 = { .s_addr = ntohl(INADDR_LOOPBACK) }; + isc_sockaddr_t sa; + char uri[256]; + UNUSED(state); + + /* Firstly, test URI generation using isc_sockaddr_t */ + isc_sockaddr_fromin(&sa, &localhostv4, 0); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0); + + /* + * The port value should be ignored, because we can get one from + * the isc_sockaddr_t object. + */ + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0); + + /* IPv6 */ + isc_sockaddr_fromin6(&sa, &in6addr_loopback, 0); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0); + + /* + * The port value should be ignored, because we can get one from + * the isc_sockaddr_t object. + */ + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0); + + /* Try to set the port numbers. */ + isc_sockaddr_setport(&sa, 44343); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0); + + isc_sockaddr_setport(&sa, 8080); + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0); + + /* + * Try to make a URI using a hostname and a port number. The + * isc_sockaddr_t object will be ignored. + */ + isc_sockaddr_any(&sa); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, "example.com", 0, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://example.com:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, "example.com", 0, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://example.com:80/dns-query", uri) == 0); + + /* Try to set the port numbers. */ + isc_sockaddr_setport(&sa, 443); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, "example.com", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://example.com:44343/dns-query", uri) == 0); + + isc_sockaddr_setport(&sa, 80); + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, "example.com", 8080, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://example.com:8080/dns-query", uri) == 0); + + /* IPv4 as the hostname - nothing fancy here */ + uri[0] = '\0'; + isc_nm_http_makeuri(false, NULL, "127.0.0.1", 8080, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:8080/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(true, NULL, "127.0.0.1", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:44343/dns-query", uri) == 0); + + /* + * A peculiar edge case: IPv6 given as the hostname (notice + * the brackets) + */ + uri[0] = '\0'; + isc_nm_http_makeuri(false, NULL, "::1", 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(true, NULL, "[::1]", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(mock_doh_uv_tcp_bind, setup_test, teardown_test) +ISC_TEST_ENTRY(doh_parse_GET_query_string) +ISC_TEST_ENTRY(doh_base64url_to_base64) +ISC_TEST_ENTRY(doh_base64_to_base64url) +ISC_TEST_ENTRY(doh_path_validation) +ISC_TEST_ENTRY(doh_connect_makeuri) +ISC_TEST_ENTRY_CUSTOM(doh_noop_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noop_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noresponse_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noresponse_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_TLS, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_TLS, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_bad_connect_uri, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/errno_test.c b/tests/isc/errno_test.c new file mode 100644 index 0000000..fbfe56a --- /dev/null +++ b/tests/isc/errno_test.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +typedef struct { + int err; + isc_result_t result; +} testpair_t; + +testpair_t testpair[] = { { EPERM, ISC_R_NOPERM }, + { ENOENT, ISC_R_FILENOTFOUND }, + { EIO, ISC_R_IOERROR }, + { EBADF, ISC_R_INVALIDFILE }, + { ENOMEM, ISC_R_NOMEMORY }, + { EACCES, ISC_R_NOPERM }, + { EEXIST, ISC_R_FILEEXISTS }, + { ENOTDIR, ISC_R_INVALIDFILE }, + { EINVAL, ISC_R_INVALIDFILE }, + { ENFILE, ISC_R_TOOMANYOPENFILES }, + { EMFILE, ISC_R_TOOMANYOPENFILES }, + { EPIPE, ISC_R_CONNECTIONRESET }, + { ENAMETOOLONG, ISC_R_INVALIDFILE }, + { ELOOP, ISC_R_INVALIDFILE }, +#ifdef EOVERFLOW + { EOVERFLOW, ISC_R_RANGE }, +#endif /* ifdef EOVERFLOW */ +#ifdef EAFNOSUPPORT + { EAFNOSUPPORT, ISC_R_FAMILYNOSUPPORT }, +#endif /* ifdef EAFNOSUPPORT */ +#ifdef EADDRINUSE + { EADDRINUSE, ISC_R_ADDRINUSE }, +#endif /* ifdef EADDRINUSE */ + { EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL }, +#ifdef ENETDOWN + { ENETDOWN, ISC_R_NETDOWN }, +#endif /* ifdef ENETDOWN */ +#ifdef ENETUNREACH + { ENETUNREACH, ISC_R_NETUNREACH }, +#endif /* ifdef ENETUNREACH */ +#ifdef ECONNABORTED + { ECONNABORTED, ISC_R_CONNECTIONRESET }, +#endif /* ifdef ECONNABORTED */ +#ifdef ECONNRESET + { ECONNRESET, ISC_R_CONNECTIONRESET }, +#endif /* ifdef ECONNRESET */ +#ifdef ENOBUFS + { ENOBUFS, ISC_R_NORESOURCES }, +#endif /* ifdef ENOBUFS */ +#ifdef ENOTCONN + { ENOTCONN, ISC_R_NOTCONNECTED }, +#endif /* ifdef ENOTCONN */ +#ifdef ETIMEDOUT + { ETIMEDOUT, ISC_R_TIMEDOUT }, +#endif /* ifdef ETIMEDOUT */ + { ECONNREFUSED, ISC_R_CONNREFUSED }, +#ifdef EHOSTDOWN + { EHOSTDOWN, ISC_R_HOSTDOWN }, +#endif /* ifdef EHOSTDOWN */ +#ifdef EHOSTUNREACH + { EHOSTUNREACH, ISC_R_HOSTUNREACH }, +#endif /* ifdef EHOSTUNREACH */ + { 0, ISC_R_UNEXPECTED } }; + +/* convert errno to ISC result */ +ISC_RUN_TEST_IMPL(isc_errno_toresult) { + isc_result_t result, expect; + size_t i; + + for (i = 0; i < sizeof(testpair) / sizeof(testpair[0]); i++) { + result = isc_errno_toresult(testpair[i].err); + expect = testpair[i].result; + assert_int_equal(result, expect); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_errno_toresult) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/file_test.c b/tests/isc/file_test.c new file mode 100644 index 0000000..6b75ba2 --- /dev/null +++ b/tests/isc/file_test.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +#define NAME "internal" +#define SHA "3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f" +#define TRUNC_SHA "3bed2cb3a3acf7b6" + +#define BAD1 "in/internal" +#define BADHASH1 "8bbb97a888791399" + +#define BAD2 "Internal" +#define BADHASH2 "2ea1842b445b0c81" + +#define F(x) "testdata/file/" x ".test" + +static void +touch(const char *filename) { + int fd; + + unlink(filename); + fd = creat(filename, 0644); + if (fd != -1) { + close(fd); + } +} + +/* test sanitized filenames */ +ISC_RUN_TEST_IMPL(isc_file_sanitize) { + isc_result_t result; + char buf[1024]; + + UNUSED(state); + + assert_return_code(chdir(TESTS_DIR), 0); + + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(NAME)), 0); + + touch(F(TRUNC_SHA)); + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(TRUNC_SHA)), 0); + + touch(F(SHA)); + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(SHA)), 0); + + result = isc_file_sanitize("testdata/file", BAD1, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(BADHASH1)), 0); + + result = isc_file_sanitize("testdata/file", BAD2, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(BADHASH2)), 0); + + unlink(F(TRUNC_SHA)); + unlink(F(SHA)); +} + +/* test filename templates */ +ISC_RUN_TEST_IMPL(isc_file_template) { + isc_result_t result; + char buf[1024]; + + UNUSED(state); + + assert_return_code(chdir(TESTS_DIR), 0); + + result = isc_file_template("/absolute/path", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/absolute/file-XXXXXXXX"); + + result = isc_file_template("relative/path", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "relative/file-XXXXXXXX"); + + result = isc_file_template("/trailing/slash/", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/trailing/slash/file-XXXXXXXX"); + + result = isc_file_template("relative/trailing/slash/", "file-XXXXXXXX", + buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "relative/trailing/slash/file-XXXXXXXX"); + + result = isc_file_template("/", "file-XXXXXXXX", buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/file-XXXXXXXX"); + + result = isc_file_template("noslash", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "file-XXXXXXXX"); + + result = isc_file_template(NULL, "file-XXXXXXXX", buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "file-XXXXXXXX"); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_file_sanitize) +ISC_TEST_ENTRY(isc_file_template) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/hash_test.c b/tests/isc/hash_test.c new file mode 100644 index 0000000..10a8c27 --- /dev/null +++ b/tests/isc/hash_test.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Hash function test */ +ISC_RUN_TEST_IMPL(isc_hash_function) { + unsigned int h1; + unsigned int h2; + + UNUSED(state); + + /* Immutability of hash function */ + h1 = isc_hash_function(NULL, 0, true); + h2 = isc_hash_function(NULL, 0, true); + + assert_int_equal(h1, h2); + + /* Hash function characteristics */ + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); + + /* Case */ + h1 = isc_hash_function("Hello world", 12, false); + h2 = isc_hash_function("heLLo WorLd", 12, false); + + assert_int_equal(h1, h2); + + /* Unequal */ + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("heLLo WorLd", 12, true); + + assert_int_not_equal(h1, h2); +} + +/* Hash function initializer test */ +ISC_RUN_TEST_IMPL(isc_hash_initializer) { + unsigned int h1; + unsigned int h2; + + UNUSED(state); + + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); + + isc_hash_set_initializer(isc_hash_get_initializer()); + + /* Hash value must not change */ + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_hash_function) +ISC_TEST_ENTRY(isc_hash_initializer) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/heap_test.c b/tests/isc/heap_test.c new file mode 100644 index 0000000..19e3ba5 --- /dev/null +++ b/tests/isc/heap_test.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +struct e { + unsigned int value; + unsigned int index; +}; + +static bool +compare(void *p1, void *p2) { + struct e *e1 = p1; + struct e *e2 = p2; + + return (e1->value < e2->value); +} + +static void +idx(void *p, unsigned int i) { + struct e *e = p; + + e->index = i; +} + +/* test isc_heap_delete() */ +ISC_RUN_TEST_IMPL(isc_heap_delete) { + isc_heap_t *heap = NULL; + struct e e1 = { 100, 0 }; + + UNUSED(state); + + isc_heap_create(mctx, compare, idx, 0, &heap); + assert_non_null(heap); + + isc_heap_insert(heap, &e1); + assert_int_equal(e1.index, 1); + + isc_heap_delete(heap, e1.index); + assert_int_equal(e1.index, 0); + + isc_heap_destroy(&heap); + assert_null(heap); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_heap_delete) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/hmac_test.c b/tests/isc/hmac_test.c new file mode 100644 index 0000000..093c6b2 --- /dev/null +++ b/tests/isc/hmac_test.c @@ -0,0 +1,926 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include + +#include "hmac.c" + +#include + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +static int +_setup(void **state) { + isc_hmac_t *hmac = isc_hmac_new(); + if (hmac == NULL) { + return (-1); + } + *state = hmac; + return (0); +} + +static int +_teardown(void **state) { + if (*state == NULL) { + return (-1); + } + isc_hmac_free(*state); + return (0); +} + +static int +_reset(void **state) { + if (*state == NULL) { + return (-1); + } + if (isc_hmac_reset(*state) != ISC_R_SUCCESS) { + return (-1); + } + return (0); +} + +ISC_RUN_TEST_IMPL(isc_hmac_new) { + UNUSED(state); + + isc_hmac_t *hmac = isc_hmac_new(); + assert_non_null(hmac); + isc_hmac_free(hmac); /* Cleanup */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_free) { + UNUSED(state); + + isc_hmac_t *hmac = isc_hmac_new(); + assert_non_null(hmac); + isc_hmac_free(hmac); /* Test freeing valid message digest context */ + isc_hmac_free(NULL); /* Test freeing NULL argument */ +} + +static void +isc_hmac_test(isc_hmac_t *hmac, const void *key, size_t keylen, + const isc_md_type_t *type, const char *buf, size_t buflen, + const char *result, const size_t repeats) { + isc_result_t res; + + assert_non_null(hmac); + assert_int_equal(isc_hmac_init(hmac, key, keylen, type), ISC_R_SUCCESS); + + for (size_t i = 0; i < repeats; i++) { + assert_int_equal(isc_hmac_update(hmac, + (const unsigned char *)buf, + buflen), + ISC_R_SUCCESS); + } + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen = sizeof(digest); + assert_int_equal(isc_hmac_final(hmac, digest, &digestlen), + ISC_R_SUCCESS); + + char hexdigest[ISC_MAX_MD_SIZE * 2 + 3]; + isc_region_t r = { .base = digest, .length = digestlen }; + isc_buffer_t b; + isc_buffer_init(&b, hexdigest, sizeof(hexdigest)); + + res = isc_hex_totext(&r, 0, "", &b); + + assert_return_code(res, ISC_R_SUCCESS); + + assert_memory_equal(hexdigest, result, (result ? strlen(result) : 0)); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_init) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + expect_assert_failure(isc_hmac_init(NULL, "", 0, ISC_MD_MD5)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, NULL), + ISC_R_NOTIMPLEMENTED); + + expect_assert_failure(isc_hmac_init(hmac, NULL, 0, ISC_MD_MD5)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_MD5), ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA1), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA224), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA256), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA384), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_update) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + /* Uses message digest context initialized in isc_hmac_init_test() */ + expect_assert_failure(isc_hmac_update(NULL, NULL, 0)); + + assert_int_equal(isc_hmac_update(hmac, NULL, 100), ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"", 0), + ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_reset) { + isc_hmac_t *hmac = *state; +#if 0 + unsigned char digest[ISC_MAX_MD_SIZE] __attribute((unused)); + unsigned int digestlen __attribute((unused)); +#endif /* if 0 */ + + assert_non_null(hmac); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"a", 1), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"b", 1), + ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + +#if 0 + /* + * This test would require OpenSSL compiled with mock_assert(), + * so this could be only manually checked that the test will + * segfault when called by hand + */ + expect_assert_failure(isc_hmac_final(hmac, digest, &digestlen)); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_final) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen = sizeof(digest); + + /* Fail when message digest context is empty */ + expect_assert_failure(isc_hmac_final(NULL, digest, &digestlen)); + /* Fail when output buffer is empty */ + expect_assert_failure(isc_hmac_final(hmac, NULL, &digestlen)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + /* Fail when the digest length pointer is empty */ + expect_assert_failure(isc_hmac_final(hmac, digest, NULL)); +} + +ISC_RUN_TEST_IMPL(isc_hmac_md5) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_MD5, TEST_INPUT(""), + "74E6F7298A9C2D168935F58C001BAD88", 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_MD5, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "9294727A3638BB1C13F48EF8158BFC9D", 1); + + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_MD5, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79" + "\x61\x20\x77\x61\x6e\x74\x20\x66\x6f" + "\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "750C783E6AB0B503EAA86E310A5DB738", 1); + + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "56BE34521D144C88DBB8C733F0E8B3F6", 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_MD5, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "697EAF0ACA3A3AEA3A75164746FFAA79", 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_MD5, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); + /* Test 6 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "AA4AE5E15272D00E95705637CE8A3B55ED402112", + 1); + /* Test 7 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data"), + "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91", + 1); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha1) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA1, TEST_INPUT(""), + "FBDB1D1B18AA6C08324B7D64B71FB76370690E1D", 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA1, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "B617318655057264E28BC0B6FB378C8EF146BE00", 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA1, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79", 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "125D7342B9AC11CD91A39AF48AA17B4F63F175D3", 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA1, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "4C9007F4026250C6BC8414F9BF50C86C2D7235DA", 1); +#if 0 + /* Test 5 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA1, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "AA4AE5E15272D00E95705637CE8A3B55ED402112", 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data"), + "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91", 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha224) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA224, TEST_INPUT(""), + "5CE14F72894662213E2748D2A6BA234B74263910CEDDE2F5" + "A9271524", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA224, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA" + "4F53684B22", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA224, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E61480" + "08FD05E44", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA224, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69" + "D1EC8333EA", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA224, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC01" + "2DE7AFEC5A", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA224, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA224, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7" + "273FA6870E", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA224, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95" + "C9F6F565D1", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha256) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA256, TEST_INPUT(""), + "B613679A0814D9EC772F95D778C35FC5FF1697C493715653" + "C6C712144292C5AD", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA256, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833D" + "A726E9376C2E32CFF7", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA256, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "5BDCC146BF60754E6A042426089575C75A003F089D2739" + "839DEC58B964EC3843", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA256, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "773EA91E36800E46854DB8EBD09181A72959098B3EF8C1" + "22D9635514CED565FE", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA256, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8" + "077A2E3FF46729665B", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA256, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA256, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5" + "140546040F0EE37F54", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA256, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713" + "938A7F51535C3A35E2", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha384) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA384, TEST_INPUT(""), + "6C1F2EE938FAD2E24BD91298474382CA218C75DB3D83E114" + "B3D4367776D14D3551289E75E8209CD4B792302840234ADC", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA384, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "AFD03944D84895626B0825F4AB46907F15F9DADBE4101E" + "C682AA034C7CEBC59CFAEA9EA9076EDE7F4AF152" + "E8B2FA9CB6", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA384, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B" + "47E42EC3736322445E8E2240CA5E69E2C78B3239" + "ECFAB21649", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA384, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9F" + "EBE83EF4E55966144B2A5AB39DC13814B94E3AB6" + "E101A34F27", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA384, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "3E8A69B7783C25851933AB6290AF6CA77A998148085000" + "9CC5577C6E1F573B4E6801DD23C4A7D679CCF8A3" + "86C674CFFB", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA384, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA384, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B58" + "8F3CD11F05033AC4C60C2EF6AB4030FE8296248D" + "F163F44952", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA384, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB" + "9ADCCEBB82461E99C5A678CC31E799176D3860E6" + "110C46523E", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha512) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA512, TEST_INPUT(""), + "B936CEE86C9F87AA5D3C6F2E84CB5A4239A5FE50480A6EC6" + "6B70AB5B1F4AC6730C6C515421B327EC1D69402E53DFB49A" + "D7381EB067B338FD7B0CB22247225D47", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA512, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2" + "787AD0B30545E17CDEDAA833B7D6B8A702038B27" + "4EAEA3F4E4BE9D914EEB61F1702E696C203A126854", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA512, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831F" + "D610270CD7EA2505549758BF75C05A994A6D034F" + "65F8F0E6FDCAEAB1A34D4A6B4B636E070A38BCE737", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA512, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A" + "3655F83E33B2279D39BF3E848279A722C806B485" + "A47E67C807B946A337BEE8942674278859E13292FB", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA512, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B87" + "2DE76F8050361EE3DBA91CA5C11AA25EB4D67927" + "5CC5788063A5F19741120C4F2DE2ADEBEB10A298DD", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA512, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA512, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEE" + "C1121B013783F8F3526B56D037E05F2598BD0FD2" + "215D6A1E5295E64F73F63F0AEC8B915A985D786598", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA512, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289" + "865DF5A32D20CDC944B6022CAC3C4982B10D5EEB" + "55C3E4DE15134676FB6DE0446065C97440FA8C6A58", + 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_hmac_new) +ISC_TEST_ENTRY_CUSTOM(isc_hmac_init, _reset, _reset) + +ISC_TEST_ENTRY_CUSTOM(isc_hmac_reset, _reset, _reset) + +ISC_TEST_ENTRY(isc_hmac_md5) +ISC_TEST_ENTRY(isc_hmac_sha1) +ISC_TEST_ENTRY(isc_hmac_sha224) +ISC_TEST_ENTRY(isc_hmac_sha256) +ISC_TEST_ENTRY(isc_hmac_sha384) +ISC_TEST_ENTRY(isc_hmac_sha512) + +ISC_TEST_ENTRY_CUSTOM(isc_hmac_update, _reset, _reset) +ISC_TEST_ENTRY_CUSTOM(isc_hmac_final, _reset, _reset) + +ISC_TEST_ENTRY(isc_hmac_free) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(_setup, _teardown) diff --git a/tests/isc/ht_test.c b/tests/isc/ht_test.c new file mode 100644 index 0000000..89e18f3 --- /dev/null +++ b/tests/isc/ht_test.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* INCLUDE LAST */ + +#define mctx __mctx +#include "ht.c" +#undef mctx + +static void +test_ht_full(int bits, uintptr_t count) { + isc_ht_t *ht = NULL; + isc_result_t result; + uintptr_t i; + + isc_ht_init(&ht, mctx, bits, ISC_HT_CASE_SENSITIVE); + assert_non_null(ht); + + for (i = 1; i < count; i++) { + /* + * Note: snprintf() is followed with strlcat() + * to ensure we are always filling the 16 byte key. + */ + unsigned char key[16]; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal((void *)i, (void *)f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_EXISTS); + } + + for (i = 1; i < count; i++) { + char key[64]; + /* + * Note: the key size is now strlen(key) which is bigger + * then the keys added above. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, (const unsigned char *)key, strlen(key), + (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + /* + * Note: case of KEY is now in capitals, + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + char key[64]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, (const unsigned char *)key, + strlen(key), &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(f, (void *)i); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_delete(ht, key, 16); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + /* + * Note: upper case KEY. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + char key[64]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_delete(ht, (const unsigned char *)key, + strlen(key)); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_ht_find(ht, (const unsigned char *)key, + strlen(key), &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + /* + * Note: case of KEY is now in capitals, + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal((void *)i, (void *)f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + isc_ht_destroy(&ht); + assert_null(ht); +} + +static void +test_ht_iterator(void) { + isc_ht_t *ht = NULL; + isc_result_t result; + isc_ht_iter_t *iter = NULL; + uintptr_t i; + uintptr_t count = 10000; + uint32_t walked; + unsigned char key[16]; + size_t tksize; + + isc_ht_init(&ht, mctx, 16, ISC_HT_CASE_SENSITIVE); + assert_non_null(ht); + for (i = 1; i <= count; i++) { + /* + * Note that the string we're snprintfing is always > 16 bytes + * so we are always filling the key. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + walked = 0; + isc_ht_iter_create(ht, &iter); + + for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS; + result = isc_ht_iter_next(iter)) + { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + walked++; + } + assert_int_equal(walked, count); + assert_int_equal(result, ISC_R_NOMORE); + + /* erase odd */ + walked = 0; + result = isc_ht_iter_first(iter); + while (result == ISC_R_SUCCESS) { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + if ((uintptr_t)v % 2 == 0) { + result = isc_ht_iter_delcurrent_next(iter); + } else { + result = isc_ht_iter_next(iter); + } + walked++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, count); + + /* erase even */ + walked = 0; + result = isc_ht_iter_first(iter); + while (result == ISC_R_SUCCESS) { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + if ((uintptr_t)v % 2 == 1) { + result = isc_ht_iter_delcurrent_next(iter); + } else { + result = isc_ht_iter_next(iter); + } + walked++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, count / 2); + + walked = 0; + for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS; + result = isc_ht_iter_next(iter)) + { + walked++; + } + + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, 0); + + isc_ht_iter_destroy(&iter); + assert_null(iter); + + isc_ht_destroy(&ht); + assert_null(ht); +} + +/* 20 bit, 200K elements test */ +ISC_RUN_TEST_IMPL(isc_ht_20) { + UNUSED(state); + test_ht_full(20, 200000); +} + +/* 8 bit, 20000 elements crowded test */ +ISC_RUN_TEST_IMPL(isc_ht_8) { + UNUSED(state); + test_ht_full(8, 20000); +} + +ISC_RUN_TEST_IMPL(isc_ht_1) { + UNUSED(state); + test_ht_full(1, 100); +} + +/* test hashtable iterator */ + +ISC_RUN_TEST_IMPL(isc_ht_iterator) { + UNUSED(state); + test_ht_iterator(); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(isc_ht_20) +ISC_TEST_ENTRY(isc_ht_8) +ISC_TEST_ENTRY(isc_ht_1) +ISC_TEST_ENTRY(isc_ht_iterator) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/lex_test.c b/tests/isc/lex_test.c new file mode 100644 index 0000000..47a40dd --- /dev/null +++ b/tests/isc/lex_test.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include + +#define AS_STR(x) (x).value.as_textregion.base + +/* check handling of 0xff */ +ISC_RUN_TEST_IMPL(lex_0xff) { + isc_result_t result; + isc_lex_t *lex = NULL; + isc_buffer_t death_buf; + isc_token_t token; + + unsigned char death[] = { EOF, 'A' }; + + UNUSED(state); + + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&death_buf, &death[0], sizeof(death)); + isc_buffer_add(&death_buf, sizeof(death)); + + result = isc_lex_openbuffer(lex, &death_buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_lex_destroy(&lex); +} + +/* check setting of source line */ +ISC_RUN_TEST_IMPL(lex_setline) { + isc_result_t result; + isc_lex_t *lex = NULL; + unsigned char text[] = "text\nto\nbe\nprocessed\nby\nlexer"; + isc_buffer_t buf; + isc_token_t token; + unsigned long line; + int i; + + UNUSED(state); + + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&buf, &text[0], sizeof(text)); + isc_buffer_add(&buf, sizeof(text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 6; i++) { + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_SUCCESS); + + line = isc_lex_getsourceline(lex); + assert_int_equal(line, 100U + i); + } + + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_EOF); + + line = isc_lex_getsourceline(lex); + assert_int_equal(line, 105U); + + isc_lex_destroy(&lex); +} + +static struct { + const char *text; + const char *string_value; + isc_result_t string_result; + isc_tokentype_t string_type; + const char *qstring_value; + isc_result_t qstring_result; + isc_tokentype_t qstring_type; + const char *qvpair_value; + isc_result_t qvpair_result; + isc_tokentype_t qvpair_type; +} parse_tests[] = { + { "", "", ISC_R_SUCCESS, isc_tokentype_eof, "", ISC_R_SUCCESS, + isc_tokentype_eof, "", ISC_R_SUCCESS, isc_tokentype_eof }, + { "1234", "1234", ISC_R_SUCCESS, isc_tokentype_string, "1234", + ISC_R_SUCCESS, isc_tokentype_string, "1234", ISC_R_SUCCESS, + isc_tokentype_string }, + { "1234=", "1234=", ISC_R_SUCCESS, isc_tokentype_string, + "1234=", ISC_R_SUCCESS, isc_tokentype_string, "1234=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "1234=foo", "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "1234=\"foo", "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0 }, + { "1234=\"foo\"", "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key", "key", ISC_R_SUCCESS, isc_tokentype_string, "key", + ISC_R_SUCCESS, isc_tokentype_string, "key", ISC_R_SUCCESS, + isc_tokentype_string }, + { "\"key=", "\"key=", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, "\"key=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "\"key=\"", "\"key=\"", ISC_R_SUCCESS, isc_tokentype_string, "key=", + ISC_R_SUCCESS, isc_tokentype_qstring, NULL, ISC_R_UNEXPECTEDEND, 0 }, + { "key=\"\"", "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a b\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a b", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a\tb\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a\tb", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + /* double quote not immediately after '=' is not special. */ + { "key=c\"a b\"", "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=c\"a", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* remove special meaning for '=' by escaping */ + { "key\\=", "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a\"", "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a\"", + ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a \"", "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a", + ISC_R_SUCCESS, isc_tokentype_string }, + /* vpair with a key of 'key\=' (would need to be deescaped) */ + { "key\\==", "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key\\==\"\"", "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\\\\\\\\", "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\\", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key=\\\\\\\"", "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\"", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* incomplete escape sequence */ + { "key=\\\"\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, + /* incomplete escape sequence */ + { "key=\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, +}; + +/*% + * string + */ +ISC_RUN_TEST_IMPL(lex_string) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_string, true); + + assert_int_equal(result, parse_tests[i].string_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].string_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].string_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].string_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +/*% + * qstring + */ +ISC_RUN_TEST_IMPL(lex_qstring) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_qstring, true); + + assert_int_equal(result, parse_tests[i].qstring_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].qstring_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qstring_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].qstring_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +/*% + * keypair is =. This has implications double quotes + * in key names. + */ +ISC_RUN_TEST_IMPL(lex_keypair) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_qvpair, true); + + assert_int_equal(result, parse_tests[i].qvpair_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].qvpair_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qvpair_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].qvpair_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(lex_0xff) +ISC_TEST_ENTRY(lex_keypair) +ISC_TEST_ENTRY(lex_setline) +ISC_TEST_ENTRY(lex_string) +ISC_TEST_ENTRY(lex_qstring) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/md_test.c b/tests/isc/md_test.c new file mode 100644 index 0000000..aff12e4 --- /dev/null +++ b/tests/isc/md_test.c @@ -0,0 +1,555 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include + +/* For FIPS_mode() */ +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include + +#include "md.c" + +#include + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +static int +_setup(void **state) { + isc_md_t *md = isc_md_new(); + if (md == NULL) { + return (-1); + } + *state = md; + return (0); +} + +static int +_teardown(void **state) { + if (*state == NULL) { + return (-1); + } + isc_md_free(*state); + return (0); +} + +static int +_reset(void **state) { + if (*state == NULL) { + return (-1); + } + if (isc_md_reset(*state) != ISC_R_SUCCESS) { + return (-1); + } + return (0); +} + +ISC_RUN_TEST_IMPL(isc_md_new) { + isc_md_t *md = isc_md_new(); + assert_non_null(md); + isc_md_free(md); /* Cleanup */ +} + +ISC_RUN_TEST_IMPL(isc_md_free) { + isc_md_t *md = isc_md_new(); + assert_non_null(md); + isc_md_free(md); /* Test freeing valid message digest context */ + isc_md_free(NULL); /* Test freeing NULL argument */ +} + +static void +isc_md_test(isc_md_t *md, const isc_md_type_t *type, const char *buf, + size_t buflen, const char *result, const size_t repeats) { + isc_result_t res; + + assert_non_null(md); + assert_int_equal(isc_md_init(md, type), ISC_R_SUCCESS); + + for (size_t i = 0; i < repeats; i++) { + assert_int_equal( + isc_md_update(md, (const unsigned char *)buf, buflen), + ISC_R_SUCCESS); + } + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + assert_int_equal(isc_md_final(md, digest, &digestlen), ISC_R_SUCCESS); + + char hexdigest[ISC_MAX_MD_SIZE * 2 + 3]; + isc_region_t r = { .base = digest, .length = digestlen }; + isc_buffer_t b; + isc_buffer_init(&b, hexdigest, sizeof(hexdigest)); + + res = isc_hex_totext(&r, 0, "", &b); + + assert_return_code(res, ISC_R_SUCCESS); + + assert_memory_equal(hexdigest, result, (result ? strlen(result) : 0)); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_init) { + isc_md_t *md = *state; + assert_non_null(md); + + expect_assert_failure(isc_md_init(NULL, ISC_MD_MD5)); + + assert_int_equal(isc_md_init(md, NULL), ISC_R_NOTIMPLEMENTED); + + assert_int_equal(isc_md_init(md, ISC_MD_MD5), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA1), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA224), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA256), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA384), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_update) { + isc_md_t *md = *state; + assert_non_null(md); + + /* Uses message digest context initialized in isc_md_init_test() */ + expect_assert_failure(isc_md_update(NULL, NULL, 0)); + + assert_int_equal(isc_md_update(md, NULL, 100), ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"", 0), + ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_reset) { + isc_md_t *md = *state; +#if 0 + unsigned char digest[ISC_MAX_MD_SIZE] __attribute((unused)); + unsigned int digestlen __attribute((unused)); +#endif /* if 0 */ + + assert_non_null(md); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"a", 1), + ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"b", 1), + ISC_R_SUCCESS); + + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + +#if 0 + /* + * This test would require OpenSSL compiled with mock_assert(), + * so this could be only manually checked that the test will + * segfault when called by hand + */ + expect_assert_failure(isc_md_final(md,digest,&digestlen)); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_md_final) { + isc_md_t *md = *state; + assert_non_null(md); + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + + /* Fail when message digest context is empty */ + expect_assert_failure(isc_md_final(NULL, digest, &digestlen)); + /* Fail when output buffer is empty */ + expect_assert_failure(isc_md_final(md, NULL, &digestlen)); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_final(md, digest, NULL), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_md5) { + isc_md_t *md = *state; + isc_md_test(md, ISC_MD_MD5, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT(""), + "D41D8CD98F00B204E9800998ECF8427E", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("a"), + "0CC175B9C0F1B6A831C399E269772661", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("abc"), + "900150983CD24FB0D6963F7D28E17F72", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("message digest"), + "F96B697D7CB7938D525A2F31AAF161D0", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("abcdefghijklmnopqrstuvwxyz"), + "C3FCD3D76192E4007DFB496CCA67E13B", 1); + isc_md_test(md, ISC_MD_MD5, + TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789"), + "D174AB98D277D9F5A5611C2C9F419D9F", 1); + isc_md_test(md, ISC_MD_MD5, + TEST_INPUT("123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890"), + "57EDF4A22BE3C955AC49DA2E2107B67A", 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha1) { + isc_md_t *md = *state; + isc_md_test(md, ISC_MD_SHA1, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT(""), + "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", 1); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("abc"), + "A9993E364706816ABA3E25717850C26C9CD0D89D", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijk" + "ljklmklmnlmnomnopnopq"), + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", 1); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("a"), + "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F", 1000000); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("01234567012345670123456701234567"), + "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452", 20); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("\x5e"), + "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46" + "\xaa\x55\xfe\x75\x71\x46"), + "82ABFF6605DBE1C17DEF12A394FA22A82B544A35", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b" + "\x4f\xba\x15\xa1\xd5\x9f\x3f\xd8\x4d\x22" + "\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e" + "\xd1\x15\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea" + "\xd2\x44\x21\xde\xd9\xc3\x25\x92\xbd\x57" + "\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a" + "\x84\xd0\xcf\x1f\x7b\xee\xad\x17\x13\xe2" + "\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" + "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83" + "\x6f\xd5\x56\x2a\x56\xca\xb1\xa2\x8e\x81" + "\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8" + "\x6e\x3b\x33\xa1\x08\xb0\x53\x07\xc0\x0a" + "\xff\x14\xa7\x68\xed\x73\x50\x60\x6a\x0f" + "\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57" + "\x7f\x9b\x38\x80\x7c\x7d\x52\x3d\x6d\x79" + "\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" + "\xcd\xbb\xfb"), + "CB0082C8F197D260991BA6A460E76E202BAD27B3", 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha224) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA224, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT(""), + "D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F", + 1); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("abc"), + "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7" + "E36C9DA7", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijklj" + "klmklmnlmnomnopnopq"), + "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B" + "1952522525", + 1); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("a"), + "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2" + "EE4EE7AD67", + 1000000); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("01234567012345670123456701234567"), + "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA" + "0EB7AB8262", + 20); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("\x07"), + "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450" + "BEE2AA8C2A", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29" + "\x9d\x6f\x9d\x93\xdf\x62"), + "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC38" + "8E56191DB1", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52" + "\x06\x22\xd1\xac\x97\xd5\xcd\xbe\x8c\xb3" + "\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba" + "\x09\xab\xc8\x53\x3c\x52\x50\x88\x7a\x43" + "\xbe\xbb\xac\x90\x6c\x2e\x18\x37\xf2\x6b" + "\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89" + "\x6b\x71\x8b\x2a\x38\x3e\xcd\xac\x16\xb9" + "\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74" + "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11" + "\x12\x24\x5f\x48\xee\x47\x0d\x39\x6c\x1e" + "\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee" + "\xa8\x14\xb6\x13\x5e\xca\x54\x39\x2b\xde" + "\xdb\x94\x89\xbc\x9b\x87\x5a\x8b\xaf\x0d" + "\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2" + "\x64\xbc\x07\x9d\x26\x9f\x2c\x0d\x7e\xdd" + "\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c" + "\x87\x82\x73"), + "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E" + "9F20D5C3A4", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha256) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA256, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT(""), + "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B93" + "4CA495991B7852B855", + 1); + + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("abc"), + "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A" + "9CB410FF61F20015AD", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijkljk" + "lmklmnlmnomnopnopq"), + "248D6A61D20638B8E5C026930C3E6039A33CE45964FF21" + "67F6ECEDD419DB06C1", + 1); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("a"), + "CDC76E5C9914FB9281A1C7E284D73E67F1809A48A49720" + "0E046D39CCC7112CD0", + 1000000); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("01234567012345670123456701234567"), + "594847328451BDFA85056225462CC1D867D877FB388DF0" + "CE35F25AB5562BFBB5", + 20); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("\x19"), + "68AA2E2EE5DFF96E3355E6C7EE373E3D6A4E17F75F9518" + "D843709C0C9BC3E3D4", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3" + "\x88\x7a\xb2\xcd\x68\x46\x52"), + "175EE69B02BA9B58E2B0A5FD13819CEA573F3940A94F82" + "5128CF4209BEABB4E8", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1" + "\x2b\x20\x52\x7a\xfe\xf0\x4d\x8a\x05\x69" + "\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76" + "\x00\x00\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08" + "\x3a\xa3\x9d\x81\x0d\xb3\x10\x77\x7d\xab" + "\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32" + "\x5f\x8b\x23\x74\xde\x7a\x4b\x5a\x58\xcb" + "\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" + "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65" + "\x92\xec\xed\xaa\x66\xca\x82\xa2\x9d\x0c" + "\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4" + "\xc0\xa4\x3f\x8d\x79\xa3\x0a\x16\x5c\xba" + "\xbe\x45\x2b\x77\x4b\x9c\x71\x09\xa9\x7d" + "\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc" + "\x10\x6a\xad\x5a\x9f\xdd\x30\x82\x57\x69" + "\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" + "\x3d\x54\xd6"), + "97DBCA7DF46D62C8A422C941DD7E835B8AD3361763F7E9" + "B2D95F4F0DA6E1CCBC", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha384) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA384, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT(""), + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07" + "434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898" + "B95B" + "", + 1); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("abc"), + "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1" + "631A8B605A43FF5BED8086072BA1E7CC2358BAEC" + "A134C825A7", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl" + "fghijklmghijklmnhijklmnoijklmnopjklmnopq" + "klmnopqrlmnopqrsmnopqrstnopqrstu"), + "09330C33F71147E83D192FC782CD1B4753111B173B3B05" + "D22FA08086E3B0F712FCC7C71A557E2DB966C3E9" + "FA91746039", + 1); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("a"), + "9D0E1809716474CB086E834E310A4A1CED149E9C00F248" + "527972CEC5704C2A5B07B8B3DC38ECC4EBAE97DD" + "D87F3D8985", + 1000000); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("01234567012345670123456701234567"), + "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A" + "70BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A" + "0D79FB4596", + 20); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("\xb9"), + "BC8089A19007C0B14195F4ECC74094FEC64F01F9092928" + "2C2FB392881578208AD466828B1C6C283D2722CF" + "0AD1AB6938", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1" + "\x0a\x7f\x4e\x08\x59\x17\x39"), + "C9A68443A005812256B8EC76B00516F0DBB74FAB26D665" + "913F194B6FFB0E91EA9967566B58109CBC675CC2" + "08E4C823F7", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb" + "\x69\x12\xec\x10\xff\xcf\x74\x79\x03\x49" + "\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21" + "\xdb\x0f\x3e\x7d\xc8\x7f\x82\x32\x64\xbb" + "\xe4\x0d\x18\x11\xc9\xea\x20\x61\xe1\xc8" + "\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02" + "\xfc\x3f\x50\x42\xe6\xbf\x58\xcb\xa8\xa2" + "\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" + "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86" + "\x5f\x25\xcc\x22\xb5\xe8\x77\x84\xa1\x2f" + "\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a" + "\x2c\xe6\x56\x5c\xbd\xf1\x3d\xca\x40\x38" + "\x32\xcf\xcb\x0e\x8b\x72\x11\xe8\x3a\xf3" + "\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5" + "\x1c\xc0\x27\xaa\xed\xef\xf8\x5a\xad\x7c" + "\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a" + "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15" + "\x1c\xb9\xbc\x51\x25\xa4\x22\xe9\x41\xde" + "\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd" + "\xd0\x96\x76\x71\x1c\xf3\xdb\x0a\x34\x40" + "\x72\x0e\x16\x15\xc1\xf2\x2f\xbc\x3c\x72" + "\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77" + "\x40\x86\x42\x14\x7e\xd0\x96"), + "4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4A" + "AF38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD2" + "0CFF1288C0", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha512) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA512, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT(""), + "CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715" + "DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877E" + "EC2F63B931BD47417A81A538327AF927DA3E", + 1); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("abc"), + "DDAF35A193617ABACC417349AE20413112E6FA4E89A97E" + "A20A9EEEE64B55D39A2192992A274FC1A836BA3C" + "23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl" + "fghijklmghijklmnhijklmnoijklmnopjklmnopq" + "klmnopqrlmnopqrsmnopqrstnopqrstu"), + "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7F" + "A17299AEADB6889018501D289E4900F7E4331B99" + "DEC4B5433AC7D329EEB6DD26545E96E55B874BE909", + 1); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("a"), + "E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044" + "285632A803AFA973EBDE0FF244877EA60A4CB043" + "2CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B", + 1000000); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("01234567012345670123456701234567"), + "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E0" + "24DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF" + "33C765CB510813A39CD5A84C4ACAA64D3F3FB7BAE9", + 20); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("\xD0"), + "9992202938E882E73E20F6B69E68A0A7149090423D93C8" + "1BAB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA" + "8306826C4AD6E74CECE9631BFA8A549B4AB3FBBA15", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81" + "\x6e\x9d\x98\xbf\xf0\xa0"), + "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75AC" + "BDD1C153C9828924C3DDEDAAFE669C5FDD0BC66F" + "630F6773988213EB1B16F517AD0DE4B2F0C95C90F8", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a" + "\x50\x2d\x65\x82\x4e\x31\xa2\x30\x54\x32" + "\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d" + "\xe1\xde\x69\x74\xbf\x49\x54\x69\xfc\x7f" + "\x33\x8f\x80\x54\xd5\x8c\x26\xc4\x93\x60" + "\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d" + "\x03\xe5\x6f\xf2\xf8\x68\x00\x2b\xc3\xe4" + "\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" + "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69" + "\x4f\xcb\xba\xf8\x8d\x95\x19\xe4\xeb\x50" + "\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc" + "\x44\x65\xc8\x82\x1a\xac\xd2\xfe\x15\xab" + "\x49\x81\x16\x4b\xbb\x6d\xc3\x2f\x96\x90" + "\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b" + "\x76\x32\x99\x41\x9c\xc4\x12\x8b\xe9\xa0" + "\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" + "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13" + "\x2e\x9a\x0d\xc6\xd3\xb1\xf8\xb2\x46\xf1" + "\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20" + "\x98\xe8\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f" + "\x47\x07\xfe\x1e\xa1\xa1\x79\x1b\xa2\xf3" + "\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9" + "\x49\xad\x47\xd7\xfb\x40\xd2"), + "C665BEFB36DA189D78822D10528CBF3B12B3EEF7260399" + "09C1A16A270D48719377966B957A878E72058477" + "9A62825C18DA26415E49A7176A894E7510FD1451F5", + 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_md_new) + +ISC_TEST_ENTRY_CUSTOM(isc_md_init, _reset, _reset) + +ISC_TEST_ENTRY_CUSTOM(isc_md_reset, _reset, _reset) + +ISC_TEST_ENTRY(isc_md_md5) +ISC_TEST_ENTRY(isc_md_sha1) + +ISC_TEST_ENTRY(isc_md_sha224) +ISC_TEST_ENTRY(isc_md_sha256) +ISC_TEST_ENTRY(isc_md_sha384) +ISC_TEST_ENTRY(isc_md_sha512) + +ISC_TEST_ENTRY_CUSTOM(isc_md_update, _reset, _reset) +ISC_TEST_ENTRY_CUSTOM(isc_md_final, _reset, _reset) + +ISC_TEST_ENTRY(isc_md_free) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(_setup, _teardown) diff --git a/tests/isc/mem_test.c b/tests/isc/mem_test.c new file mode 100644 index 0000000..f2bbdbd --- /dev/null +++ b/tests/isc/mem_test.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mem_p.h" + +#include + +#define MP1_FREEMAX 10 +#define MP1_FILLCNT 10 +#define MP1_MAXALLOC 30 + +#define MP2_FREEMAX 25 +#define MP2_FILLCNT 25 + +/* general memory system tests */ +ISC_RUN_TEST_IMPL(isc_mem) { + void *items1[50]; + void *items2[50]; + void *tmp; + isc_mempool_t *mp1 = NULL, *mp2 = NULL; + unsigned int i, j; + int rval; + + UNUSED(state); + + isc_mempool_create(mctx, 24, &mp1); + isc_mempool_create(mctx, 31, &mp2); + + isc_mempool_setfreemax(mp1, MP1_FREEMAX); + isc_mempool_setfillcount(mp1, MP1_FILLCNT); + + /* + * Allocate MP1_MAXALLOC items from the pool. This is our max. + */ + for (i = 0; i < MP1_MAXALLOC; i++) { + items1[i] = isc_mempool_get(mp1); + assert_non_null(items1[i]); + } + + /* + * Free the first 11 items. Verify that there are 10 free items on + * the free list (which is our max). + */ + for (i = 0; i < 11; i++) { + isc_mempool_put(mp1, items1[i]); + items1[i] = NULL; + } + +#if !__SANITIZE_ADDRESS__ + rval = isc_mempool_getfreecount(mp1); + assert_int_equal(rval, 10); +#endif /* !__SANITIZE_ADDRESS__ */ + + rval = isc_mempool_getallocated(mp1); + assert_int_equal(rval, 19); + + /* + * Now, beat up on mp2 for a while. Allocate 50 items, then free + * them, then allocate 50 more, etc. + */ + + isc_mempool_setfreemax(mp2, 25); + isc_mempool_setfillcount(mp2, 25); + + for (j = 0; j < 500000; j++) { + for (i = 0; i < 50; i++) { + items2[i] = isc_mempool_get(mp2); + assert_non_null(items2[i]); + } + for (i = 0; i < 50; i++) { + isc_mempool_put(mp2, items2[i]); + items2[i] = NULL; + } + } + + /* + * Free all the other items and blow away this pool. + */ + for (i = 11; i < MP1_MAXALLOC; i++) { + isc_mempool_put(mp1, items1[i]); + items1[i] = NULL; + } + + isc_mempool_destroy(&mp1); + isc_mempool_destroy(&mp2); + + isc_mempool_create(mctx, 2, &mp1); + + tmp = isc_mempool_get(mp1); + assert_non_null(tmp); + + isc_mempool_put(mp1, tmp); + + isc_mempool_destroy(&mp1); +} + +#if defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) +/* aligned memory system tests */ +ISC_RUN_TEST_IMPL(isc_mem_aligned) { + isc_mem_t *mctx2 = NULL; + void *ptr; + size_t alignment; + uintptr_t aligned; + + UNUSED(state); + + /* Check different alignment sizes up to the page size */ + for (alignment = sizeof(void *); alignment <= 4096; alignment *= 2) { + size_t size = alignment / 2 - 1; + ptr = isc_mem_get_aligned(mctx, size, alignment); + + /* Check if the pointer is properly aligned */ + aligned = (((uintptr_t)ptr / alignment) * alignment); + assert_ptr_equal(aligned, (uintptr_t)ptr); + + /* Check if we can resize to range */ + ptr = isc_mem_reget_aligned(mctx, ptr, size, + size * 2 + alignment, alignment); + + /* Check if the pointer is still properly aligned */ + aligned = (((uintptr_t)ptr / alignment) * alignment); + assert_ptr_equal(aligned, (uintptr_t)ptr); + + isc_mem_put_aligned(mctx, ptr, size * 2 + alignment, alignment); + + /* Check whether isc_mem_putanddetach_detach() also works */ + isc_mem_create(&mctx2); + ptr = isc_mem_get_aligned(mctx2, size, alignment); + isc_mem_putanddetach_aligned(&mctx2, ptr, size, alignment); + } +} +#endif /* defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) */ + +/* test TotalUse calculation */ +ISC_RUN_TEST_IMPL(isc_mem_total) { + isc_mem_t *mctx2 = NULL; + size_t before, after; + ssize_t diff; + int i; + + UNUSED(state); + + /* Local alloc, free */ + mctx2 = NULL; + isc_mem_create(&mctx2); + + before = isc_mem_total(mctx2); + + for (i = 0; i < 100000; i++) { + void *ptr; + + ptr = isc_mem_get(mctx2, 2048); + isc_mem_put(mctx2, ptr, 2048); + } + + after = isc_mem_total(mctx2); + diff = after - before; + + assert_int_equal(diff, (2048) * 100000); + + /* ISC_MEMFLAG_INTERNAL */ + + before = isc_mem_total(mctx); + + for (i = 0; i < 100000; i++) { + void *ptr; + + ptr = isc_mem_get(mctx, 2048); + isc_mem_put(mctx, ptr, 2048); + } + + after = isc_mem_total(mctx); + diff = after - before; + + assert_int_equal(diff, (2048) * 100000); + + isc_mem_destroy(&mctx2); +} + +/* test InUse calculation */ +ISC_RUN_TEST_IMPL(isc_mem_inuse) { + isc_mem_t *mctx2 = NULL; + size_t before, after; + ssize_t diff; + void *ptr; + + UNUSED(state); + + mctx2 = NULL; + isc_mem_create(&mctx2); + + before = isc_mem_inuse(mctx2); + ptr = isc_mem_allocate(mctx2, 1024000); + isc_mem_free(mctx2, ptr); + after = isc_mem_inuse(mctx2); + + diff = after - before; + + assert_int_equal(diff, 0); + + isc_mem_destroy(&mctx2); +} + +ISC_RUN_TEST_IMPL(isc_mem_zeroget) { + uint8_t *data = NULL; + UNUSED(state); + + data = isc_mem_get(mctx, 0); + assert_non_null(data); + isc_mem_put(mctx, data, 0); +} + +#define REGET_INIT_SIZE 1024 +#define REGET_GROW_SIZE 2048 +#define REGET_SHRINK_SIZE 512 + +ISC_RUN_TEST_IMPL(isc_mem_reget) { + uint8_t *data = NULL; + + UNUSED(state); + + /* test that we can reget NULL */ + data = isc_mem_reget(mctx, NULL, 0, REGET_INIT_SIZE); + assert_non_null(data); + isc_mem_put(mctx, data, REGET_INIT_SIZE); + + /* test that we can re-get a zero-length allocation */ + data = isc_mem_get(mctx, 0); + assert_non_null(data); + + data = isc_mem_reget(mctx, data, 0, REGET_INIT_SIZE); + assert_non_null(data); + + for (size_t i = 0; i < REGET_INIT_SIZE; i++) { + data[i] = i % UINT8_MAX; + } + + data = isc_mem_reget(mctx, data, REGET_INIT_SIZE, REGET_GROW_SIZE); + assert_non_null(data); + + for (size_t i = 0; i < REGET_INIT_SIZE; i++) { + assert_int_equal(data[i], i % UINT8_MAX); + } + + for (size_t i = REGET_GROW_SIZE; i > 0; i--) { + data[i - 1] = i % UINT8_MAX; + } + + data = isc_mem_reget(mctx, data, REGET_GROW_SIZE, REGET_SHRINK_SIZE); + assert_non_null(data); + + for (size_t i = REGET_SHRINK_SIZE; i > 0; i--) { + assert_int_equal(data[i - 1], i % UINT8_MAX); + } + + isc_mem_put(mctx, data, REGET_SHRINK_SIZE); +} + +#if ISC_MEM_TRACKLINES + +/* test mem with no flags */ +ISC_RUN_TEST_IMPL(isc_mem_noflags) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p, *q; + FILE *f; + void *ptr; + + result = isc_stdio_open("mem.output", "w", &f); + assert_int_equal(result, ISC_R_SUCCESS); + + UNUSED(state); + + isc_mem_create(&mctx2); + isc_mem_debugging = 0; + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + buf[sizeof(buf) - 1] = 0; + + p = strchr(buf, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + p += 2; + q = strchr(p, '\n'); + assert_non_null(q); + *q = '\0'; + assert_string_equal(p, "None."); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; +} + +/* test mem with record flag */ +ISC_RUN_TEST_IMPL(isc_mem_recordflag) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + + result = isc_stdio_open("mem.output", "w", &f); + assert_int_equal(result, ISC_R_SUCCESS); + + UNUSED(state); + + isc_mem_create(&mctx2); + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + buf[sizeof(buf) - 1] = 0; + + p = strchr(buf, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + assert_memory_equal(p + 2, "ptr ", 4); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_int_equal(strlen(p), 1); +} + +/* test mem with trace flag */ +ISC_RUN_TEST_IMPL(isc_mem_traceflag) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + + /* redirect stderr so we can check trace output */ + f = freopen("mem.output", "w", stderr); + assert_non_null(f); + + UNUSED(state); + + isc_mem_create(&mctx2); + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + /* return stderr to TTY so we can see errors */ + f = freopen("/dev/tty", "w", stderr); + + buf[sizeof(buf) - 1] = 0; + + assert_memory_equal(buf, "add ", 4); + p = strchr(buf, '\n'); + assert_non_null(p); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + assert_memory_equal(p + 2, "ptr ", 4); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_memory_equal(p + 1, "del ", 4); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; +} +#endif /* if ISC_MEM_TRACKLINES */ + +#if !defined(__SANITIZE_THREAD__) + +#define ITERS 512 +#define NUM_ITEMS 1024 /* 768 */ +#define ITEM_SIZE 65534 + +static atomic_size_t mem_size; + +static isc_threadresult_t +mem_thread(isc_threadarg_t arg) { + isc_mem_t *mctx2 = (isc_mem_t *)arg; + void *items[NUM_ITEMS]; + size_t size = atomic_load(&mem_size); + while (!atomic_compare_exchange_weak(&mem_size, &size, size / 2)) { + ; + } + + for (int i = 0; i < ITERS; i++) { + for (int j = 0; j < NUM_ITEMS; j++) { + items[j] = isc_mem_get(mctx2, size); + } + for (int j = 0; j < NUM_ITEMS; j++) { + isc_mem_put(mctx2, items[j], size); + } + } + + return ((isc_threadresult_t)0); +} + +ISC_RUN_TEST_IMPL(isc_mem_benchmark) { + int nthreads = ISC_MAX(ISC_MIN(isc_os_ncpus(), 32), 1); + isc_thread_t threads[32]; + isc_time_t ts1, ts2; + double t; + isc_result_t result; + + UNUSED(state); + + atomic_init(&mem_size, ITEM_SIZE); + + result = isc_time_now(&ts1); + assert_int_equal(result, ISC_R_SUCCESS); + + for (int i = 0; i < nthreads; i++) { + isc_thread_create(mem_thread, mctx, &threads[i]); + } + for (int i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + result = isc_time_now(&ts2); + assert_int_equal(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("[ TIME ] isc_mem_benchmark: " + "%d isc_mem_{get,put} calls, %f seconds, %f " + "calls/second\n", + nthreads * ITERS * NUM_ITEMS, t / 1000000.0, + (nthreads * ITERS * NUM_ITEMS) / (t / 1000000.0)); +} + +#endif /* __SANITIZE_THREAD */ + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_mem) +#if defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) +ISC_TEST_ENTRY(isc_mem_aligned) +#endif /* defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) */ +ISC_TEST_ENTRY(isc_mem_total) +ISC_TEST_ENTRY(isc_mem_inuse) +ISC_TEST_ENTRY(isc_mem_zeroget) +ISC_TEST_ENTRY(isc_mem_reget) + +#if !defined(__SANITIZE_THREAD__) +ISC_TEST_ENTRY(isc_mem_benchmark) +#endif /* __SANITIZE_THREAD__ */ +#if ISC_MEM_TRACKLINES +ISC_TEST_ENTRY(isc_mem_noflags) +ISC_TEST_ENTRY(isc_mem_recordflag) +/* + * traceflag_test closes stderr, which causes weird + * side effects for any next test trying to use libuv. + * This test has to be the last one to avoid problems. + */ +ISC_TEST_ENTRY(isc_mem_traceflag) +#endif /* if ISC_MEM_TRACKLINES */ + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/netaddr_test.c b/tests/isc/netaddr_test.c new file mode 100644 index 0000000..2394e11 --- /dev/null +++ b/tests/isc/netaddr_test.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +/* test isc_netaddr_isnetzero() */ +ISC_RUN_TEST_IMPL(netaddr_isnetzero) { + unsigned int i; + struct in_addr ina; + struct { + const char *address; + bool expect; + } tests[] = { { "0.0.0.0", true }, { "0.0.0.1", true }, + { "0.0.1.2", true }, { "0.1.2.3", true }, + { "10.0.0.0", false }, { "10.9.0.0", false }, + { "10.9.8.0", false }, { "10.9.8.7", false }, + { "127.0.0.0", false }, { "127.0.0.1", false } }; + isc_netaddr_t netaddr; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + bool result; + ina.s_addr = inet_addr(tests[i].address); + isc_netaddr_fromin(&netaddr, &ina); + result = isc_netaddr_isnetzero(&netaddr); + assert_int_equal(result, tests[i].expect); + } +} + +/* test isc_netaddr_masktoprefixlen() calculates correct prefix lengths */ +ISC_RUN_TEST_IMPL(netaddr_masktoprefixlen) { + struct in_addr na_a; + struct in_addr na_b; + struct in_addr na_c; + struct in_addr na_d; + isc_netaddr_t ina_a; + isc_netaddr_t ina_b; + isc_netaddr_t ina_c; + isc_netaddr_t ina_d; + unsigned int plen; + + UNUSED(state); + + assert_true(inet_pton(AF_INET, "0.0.0.0", &na_a) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.254", &na_b) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.255", &na_c) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.0", &na_d) >= 0); + + isc_netaddr_fromin(&ina_a, &na_a); + isc_netaddr_fromin(&ina_b, &na_b); + isc_netaddr_fromin(&ina_c, &na_c); + isc_netaddr_fromin(&ina_d, &na_d); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_a, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 0); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_b, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 31); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_c, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 32); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_d, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 24); +} + +/* check multicast addresses are detected properly */ +ISC_RUN_TEST_IMPL(netaddr_multicast) { + unsigned int i; + struct { + int family; + const char *addr; + bool is_multicast; + } tests[] = { + { AF_INET, "1.2.3.4", false }, { AF_INET, "4.3.2.1", false }, + { AF_INET, "224.1.1.1", true }, { AF_INET, "1.1.1.244", false }, + { AF_INET6, "::1", false }, { AF_INET6, "ff02::1", true } + }; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + isc_netaddr_t na; + struct in_addr in; + struct in6_addr in6; + int r; + + if (tests[i].family == AF_INET) { + r = inet_pton(AF_INET, tests[i].addr, + (unsigned char *)&in); + assert_int_equal(r, 1); + isc_netaddr_fromin(&na, &in); + } else { + r = inet_pton(AF_INET6, tests[i].addr, + (unsigned char *)&in6); + assert_int_equal(r, 1); + isc_netaddr_fromin6(&na, &in6); + } + + assert_int_equal(isc_netaddr_ismulticast(&na), + tests[i].is_multicast); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(netaddr_isnetzero) +ISC_TEST_ENTRY(netaddr_masktoprefixlen) +ISC_TEST_ENTRY(netaddr_multicast) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/netmgr_test.c b/tests/isc/netmgr_test.c new file mode 100644 index 0000000..a20db6b --- /dev/null +++ b/tests/isc/netmgr_test.c @@ -0,0 +1,2897 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include "netmgr/netmgr-int.h" +#include "netmgr/udp.c" +#include "netmgr/uv-compat.c" +#include "netmgr/uv-compat.h" +#include "netmgr_p.h" +#pragma GCC diagnostic pop + +#include + +typedef void (*stream_connect_function)(isc_nm_t *nm); + +static void +connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg); +static void +connect_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg); + +isc_nm_t *listen_nm = NULL; +isc_nm_t *connect_nm = NULL; + +static isc_sockaddr_t udp_listen_addr; +static isc_sockaddr_t udp_connect_addr; + +static isc_sockaddr_t tcp_listen_addr; +static isc_sockaddr_t tcp_connect_addr; +static isc_tlsctx_t *tcp_listen_tlsctx = NULL; +static isc_tlsctx_t *tcp_connect_tlsctx = NULL; +static isc_tlsctx_client_session_cache_t *tcp_tlsctx_client_sess_cache = NULL; + +static uint64_t send_magic = 0; +static uint64_t stop_magic = 0; + +static isc_region_t send_msg = { .base = (unsigned char *)&send_magic, + .length = sizeof(send_magic) }; + +static isc_region_t stop_msg = { .base = (unsigned char *)&stop_magic, + .length = sizeof(stop_magic) }; + +static atomic_bool do_send = false; + +static atomic_int_fast64_t nsends; +static int_fast64_t esends; /* expected sends */ + +static atomic_int_fast64_t ssends = 0; +static atomic_int_fast64_t sreads = 0; +static atomic_int_fast64_t saccepts = 0; + +static atomic_int_fast64_t cconnects = 0; +static atomic_int_fast64_t csends = 0; +static atomic_int_fast64_t creads = 0; +static atomic_int_fast64_t ctimeouts = 0; + +static isc_refcount_t active_cconnects; +static isc_refcount_t active_csends; +static isc_refcount_t active_creads; +static isc_refcount_t active_ssends; +static isc_refcount_t active_sreads; + +static isc_quota_t listener_quota; +static atomic_bool check_listener_quota; + +static bool skip_long_tests = false; + +static bool allow_send_back = false; +static bool noanswer = false; +static bool stream_use_TLS = false; + +static isc_nm_recv_cb_t connect_readcb = NULL; + +#define SKIP_IN_CI \ + if (skip_long_tests) { \ + skip(); \ + return; \ + } + +#define NSENDS 100 + +/* Timeout for soft-timeout tests (0.05 seconds) */ +#define T_SOFT 50 + +/* Timeouts in miliseconds */ +#define T_INIT 120 * 1000 +#define T_IDLE 120 * 1000 +#define T_KEEPALIVE 120 * 1000 +#define T_ADVERTISED 120 * 1000 +#define T_CONNECT 30 * 1000 + +/* Wait for 1 second (1000 milliseconds) */ +#define WAIT_REPEATS 1000 +#define T_WAIT 1 /* 1 millisecond */ + +#define WAIT_FOR(v, op, val) \ + { \ + X(v); \ + int_fast64_t __r = WAIT_REPEATS; \ + int_fast64_t __o = 0; \ + do { \ + int_fast64_t __l = atomic_load(&v); \ + if (__l op val) { \ + break; \ + }; \ + if (__o == __l) { \ + __r--; \ + } else { \ + __r = WAIT_REPEATS; \ + } \ + __o = __l; \ + isc_test_nap(T_WAIT); \ + } while (__r > 0); \ + X(v); \ + P(__r); \ + assert_true(atomic_load(&v) op val); \ + } + +#define WAIT_FOR_EQ(v, val) WAIT_FOR(v, ==, val) +#define WAIT_FOR_NE(v, val) WAIT_FOR(v, !=, val) +#define WAIT_FOR_LE(v, val) WAIT_FOR(v, <=, val) +#define WAIT_FOR_LT(v, val) WAIT_FOR(v, <, val) +#define WAIT_FOR_GE(v, val) WAIT_FOR(v, >=, val) +#define WAIT_FOR_GT(v, val) WAIT_FOR(v, >, val) + +#define DONE() atomic_store(&do_send, false); + +#define CHECK_RANGE_FULL(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v > 1); \ + } + +#define CHECK_RANGE_HALF(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v > 1); \ + } + +/* Enable this to print values while running tests */ +#undef PRINT_DEBUG +#ifdef PRINT_DEBUG +#define X(v) \ + fprintf(stderr, "%s:%s:%d:%s = %" PRId64 "\n", __func__, __FILE__, \ + __LINE__, #v, atomic_load(&v)) +#define P(v) fprintf(stderr, #v " = %" PRId64 "\n", v) +#define F() \ + fprintf(stderr, "%s(%p, %s, %p)\n", __func__, handle, \ + isc_result_totext(eresult), cbarg) +#else +#define X(v) +#define P(v) +#define F() +#endif + +#define atomic_assert_int_eq(val, exp) assert_int_equal(atomic_load(&val), exp) +#define atomic_assert_int_ne(val, exp) \ + assert_int_not_equal(atomic_load(&val), exp) +#define atomic_assert_int_le(val, exp) assert_true(atomic_load(&val) <= exp) +#define atomic_assert_int_lt(val, exp) assert_true(atomic_load(&val) > exp) +#define atomic_assert_int_ge(val, exp) assert_true(atomic_load(&val) >= exp) +#define atomic_assert_int_gt(val, exp) assert_true(atomic_load(&val) > exp) + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + socklen_t addrlen = sizeof(*addr); + uv_os_sock_t fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + isc__nm_closesocket(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + isc__nm_closesocket(fd); + return (r); + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + isc__nm_closesocket(fd); + return (r); + } +#endif + + return (fd); +} + +static int +setup_test(void **state __attribute__((unused))) { + char *env_workers = getenv("ISC_TASK_WORKERS"); + uv_os_sock_t tcp_listen_sock = -1; + uv_os_sock_t udp_listen_sock = -1; + size_t nworkers; + + if (env_workers != NULL) { + workers = atoi(env_workers); + } else { + workers = isc_os_ncpus(); + } + INSIST(workers > 0); + nworkers = ISC_MAX(ISC_MIN(workers, 32), 1); + + if (getenv("CI") != NULL && getenv("CI_ENABLE_ALL_TESTS") == NULL) { + skip_long_tests = true; + esends = nworkers; + } else { + esends = NSENDS * nworkers; + } + + udp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0); + + udp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + udp_listen_sock = setup_ephemeral_port(&udp_listen_addr, SOCK_DGRAM); + if (udp_listen_sock < 0) { + return (-1); + } + isc__nm_closesocket(udp_listen_sock); + udp_listen_sock = -1; + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + + tcp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM); + if (tcp_listen_sock < 0) { + return (-1); + } + isc__nm_closesocket(tcp_listen_sock); + tcp_listen_sock = -1; + + atomic_store(&do_send, true); + atomic_store(&nsends, esends); + + atomic_store(&saccepts, 0); + atomic_store(&sreads, 0); + atomic_store(&ssends, 0); + + atomic_store(&cconnects, 0); + atomic_store(&csends, 0); + atomic_store(&creads, 0); + atomic_store(&ctimeouts, 0); + allow_send_back = false; + stream_use_TLS = false; + + isc_refcount_init(&active_cconnects, 0); + isc_refcount_init(&active_csends, 0); + isc_refcount_init(&active_creads, 0); + isc_refcount_init(&active_ssends, 0); + isc_refcount_init(&active_sreads, 0); + + isc_nonce_buf(&send_magic, sizeof(send_magic)); + isc_nonce_buf(&stop_magic, sizeof(stop_magic)); + if (send_magic == stop_magic) { + return (-1); + } + + isc__netmgr_create(mctx, nworkers, &listen_nm); + assert_non_null(listen_nm); + isc_nm_settimeouts(listen_nm, T_INIT, T_IDLE, T_KEEPALIVE, + T_ADVERTISED); + + isc__netmgr_create(mctx, nworkers, &connect_nm); + assert_non_null(connect_nm); + isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE, + T_ADVERTISED); + + isc_quota_init(&listener_quota, 0); + atomic_store(&check_listener_quota, false); + + connect_readcb = connect_read_cb; + noanswer = false; + + if (isc_tlsctx_createserver(NULL, NULL, &tcp_listen_tlsctx) != + ISC_R_SUCCESS) + { + return (-1); + } + if (isc_tlsctx_createclient(&tcp_connect_tlsctx) != ISC_R_SUCCESS) { + return (-1); + } + + isc_tlsctx_enable_dot_client_alpn(tcp_connect_tlsctx); + + isc_tlsctx_client_session_cache_create( + mctx, tcp_connect_tlsctx, + ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, + &tcp_tlsctx_client_sess_cache); + + return (0); +} + +static int +teardown_test(void **state __attribute__((unused))) { + UNUSED(state); + + isc_tlsctx_free(&tcp_connect_tlsctx); + isc_tlsctx_free(&tcp_listen_tlsctx); + + isc__netmgr_destroy(&connect_nm); + assert_null(connect_nm); + + isc__netmgr_destroy(&listen_nm); + assert_null(listen_nm); + + WAIT_FOR_EQ(active_cconnects, 0); + WAIT_FOR_EQ(active_csends, 0); + WAIT_FOR_EQ(active_csends, 0); + WAIT_FOR_EQ(active_ssends, 0); + WAIT_FOR_EQ(active_sreads, 0); + + isc_refcount_destroy(&active_cconnects); + isc_refcount_destroy(&active_csends); + isc_refcount_destroy(&active_creads); + isc_refcount_destroy(&active_ssends); + isc_refcount_destroy(&active_sreads); + + isc_tlsctx_client_session_cache_detach(&tcp_tlsctx_client_sess_cache); + + return (0); +} + +/* Callbacks */ + +static void +noop_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(region); + UNUSED(cbarg); +} + +static unsigned int +noop_accept_cb(isc_nmhandle_t *handle, unsigned int result, void *cbarg) { + UNUSED(handle); + UNUSED(cbarg); + + if (result == ISC_R_SUCCESS) { + (void)atomic_fetch_add(&saccepts, 1); + } + + return (0); +} + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg); + +static void +connect_send(isc_nmhandle_t *handle); + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *sendhandle = handle; + + assert_non_null(sendhandle); + + UNUSED(cbarg); + + F(); + + if (eresult != ISC_R_SUCCESS) { + /* Send failed, we need to stop reading too */ + isc_nm_cancelread(handle); + goto unref; + } + + atomic_fetch_add(&csends, 1); +unref: + isc_refcount_decrement(&active_csends); + isc_nmhandle_detach(&sendhandle); +} + +static void +connect_send(isc_nmhandle_t *handle) { + isc_nmhandle_t *sendhandle = NULL; + isc_refcount_increment0(&active_csends); + isc_nmhandle_attach(handle, &sendhandle); + isc_nmhandle_setwritetimeout(handle, T_IDLE); + if (atomic_fetch_sub(&nsends, 1) > 1) { + isc_nm_send(sendhandle, &send_msg, connect_send_cb, NULL); + } else { + isc_nm_send(sendhandle, &stop_msg, connect_send_cb, NULL); + } +} + +static void +connect_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + UNUSED(cbarg); + + assert_non_null(handle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + assert_true(region->length >= sizeof(magic)); + + atomic_fetch_add(&creads, 1); + + memmove(&magic, region->base, sizeof(magic)); + + assert_true(magic == stop_magic || magic == send_magic); + + if (magic == send_magic && allow_send_back) { + connect_send(handle); + return; + } + +unref: + isc_refcount_decrement(&active_creads); + isc_nmhandle_detach(&handle); +} + +static void +connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + isc_refcount_decrement(&active_cconnects); + + if (eresult != ISC_R_SUCCESS || connect_readcb == NULL) { + return; + } + + atomic_fetch_add(&cconnects, 1); + + isc_refcount_increment0(&active_creads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, connect_readcb, NULL); + + connect_send(handle); +} + +static void +listen_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *sendhandle = handle; + + UNUSED(cbarg); + UNUSED(eresult); + + assert_non_null(sendhandle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + atomic_fetch_add(&ssends, 1); +unref: + isc_nmhandle_detach(&sendhandle); + isc_refcount_decrement(&active_ssends); +} + +static void +listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + assert_non_null(handle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + atomic_fetch_add(&sreads, 1); + + assert_true(region->length >= sizeof(magic)); + + memmove(&magic, region->base, sizeof(magic)); + assert_true(magic == stop_magic || magic == send_magic); + + if (magic == send_magic) { + if (!noanswer) { + isc_nmhandle_t *sendhandle = NULL; + isc_nmhandle_attach(handle, &sendhandle); + isc_refcount_increment0(&active_ssends); + isc_nmhandle_setwritetimeout(sendhandle, T_IDLE); + isc_nm_send(sendhandle, &send_msg, listen_send_cb, + cbarg); + } + return; + } + +unref: + if (handle == cbarg) { + isc_refcount_decrement(&active_sreads); + isc_nmhandle_detach(&handle); + } +} + +static isc_result_t +listen_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(cbarg); + + F(); + + return (eresult); +} + +static isc_result_t +stream_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + if (eresult != ISC_R_SUCCESS) { + return (eresult); + } + + atomic_fetch_add(&saccepts, 1); + + isc_refcount_increment0(&active_sreads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, listen_read_cb, readhandle); + + return (ISC_R_SUCCESS); +} + +typedef void (*connect_func)(isc_nm_t *); + +static isc_threadresult_t +connect_thread(isc_threadarg_t arg) { + connect_func connect = (connect_func)arg; + isc_sockaddr_t connect_addr; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + while (atomic_load(&do_send)) { + uint_fast32_t active = + isc_refcount_increment0(&active_cconnects); + if (active > workers) { + /* + * If we have more active connections than workers, + * start slowing down the connections to prevent the + * thundering herd problem. + */ + isc_test_nap(active - workers); + } + connect(connect_nm); + } + + return ((isc_threadresult_t)0); +} + +/* UDP */ + +static void +udp_connect(isc_nm_t *nm) { + isc_nm_udpconnect(nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_open) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_open, UV_ENOMEM); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_bind) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_bind, UV_EADDRINUSE); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_recv_start) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_recv_start, UV_EADDRINUSE); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_open) { + WILL_RETURN(uv_udp_open, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_bind) { + WILL_RETURN(uv_udp_bind, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_connect) { + WILL_RETURN(uv_udp_connect, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} +#endif + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_recv_buffer_size) { + WILL_RETURN(uv_recv_buffer_size, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_send_buffer_size) { + WILL_RETURN(uv_send_buffer_size, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(udp_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(udp_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(csends, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +timeout_retry_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + UNUSED(region); + UNUSED(cbarg); + + assert_non_null(handle); + + F(); + + if (eresult == ISC_R_TIMEDOUT && atomic_load(&csends) < 5) { + isc_nmhandle_settimeout(handle, T_SOFT); + connect_send(handle); + return; + } + + atomic_fetch_add(&ctimeouts, 1); + + isc_refcount_decrement(&active_creads); + isc_nmhandle_detach(&handle); +} + +ISC_RUN_TEST_IMPL(udp_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Listen using the noop callback so that client reads will time out. + */ + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Connect with client timeout set to 0.05 seconds, then sleep for at + * least a second for each 'tick'. timeout_retry_cb() will give up + * after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(udp_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(udp_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(udp_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(udp_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(udp_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(udp_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* Common stream protocols code */ + +static isc_quota_t * +tcp_listener_init_quota(size_t nthreads) { + isc_quota_t *quotap = NULL; + if (atomic_load(&check_listener_quota)) { + unsigned max_quota = ISC_MAX(nthreads / 2, 1); + isc_quota_max(&listener_quota, max_quota); + quotap = &listener_quota; + } + return (quotap); +} + +static void +tcp_connect(isc_nm_t *nm) { + isc_nm_tcpconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +#if HAVE_LIBNGHTTP2 +static void +tls_connect(isc_nm_t *nm); +#endif + +static stream_connect_function +get_stream_connect_function(void) { +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + return (tls_connect); + } +#endif + return (tcp_connect); +} + +static isc_result_t +stream_listen(isc_nm_accept_cb_t accept_cb, void *accept_cbarg, + size_t extrahandlesize, int backlog, isc_quota_t *quota, + isc_nmsocket_t **sockp) { + isc_result_t result = ISC_R_SUCCESS; + +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + result = isc_nm_listentls(listen_nm, &tcp_listen_addr, + accept_cb, accept_cbarg, + extrahandlesize, backlog, quota, + tcp_listen_tlsctx, sockp); + return (result); + } +#endif + result = isc_nm_listentcp(listen_nm, &tcp_listen_addr, accept_cb, + accept_cbarg, extrahandlesize, backlog, quota, + sockp); + + return (result); +} + +static void +stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout, + size_t extrahandlesize) { +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + isc_nm_tlsconnect(connect_nm, &tcp_connect_addr, + &tcp_listen_addr, cb, cbarg, + tcp_connect_tlsctx, + tcp_tlsctx_client_sess_cache, timeout, 0); + return; + } +#endif + isc_nm_tcpconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, cb, + cbarg, timeout, extrahandlesize); +} + +static void +stream_noop(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = stream_listen(noop_accept_cb, NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_noresponse(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = stream_listen(noop_accept_cb, NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_timeout_recovery(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = stream_listen(stream_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the client timeouts to 0.05 seconds. + */ + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + connect_readcb = timeout_retry_cb; + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +static void +stream_recv_one(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_quota_t *quotap = tcp_listener_init_quota(1); + + atomic_store(&nsends, 1); + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_recv_two(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_quota_t *quotap = tcp_listener_init_quota(1); + + atomic_store(&nsends, 2); + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +static void +stream_recv_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends); + } + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +static void +stream_recv_half_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +stream_half_recv_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +stream_half_recv_half_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* TCP */ +ISC_RUN_TEST_IMPL(tcp_noop) { stream_noop(state); } + +ISC_RUN_TEST_IMPL(tcp_noresponse) { stream_noresponse(state); } + +ISC_RUN_TEST_IMPL(tcp_timeout_recovery) { stream_timeout_recovery(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_one) { stream_recv_one(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_two) { stream_recv_two(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_send) { + SKIP_IN_CI; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send) { + SKIP_IN_CI; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send) { + SKIP_IN_CI; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send) { + SKIP_IN_CI; + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_sendback) { + SKIP_IN_CI; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_sendback) { + SKIP_IN_CI; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_sendback) { + SKIP_IN_CI; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_sendback) { + SKIP_IN_CI; + stream_half_recv_half_send(state); +} + +/* TCP Quota */ + +ISC_RUN_TEST_IMPL(tcp_recv_one_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_two_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_half_recv_half_send(state); +} + +/* TCPDNS */ + +static void +tcpdns_connect(isc_nm_t *nm) { + isc_nm_tcpdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + isc_refcount_increment0(&active_cconnects); + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + if (result != ISC_R_SUCCESS) { + isc_refcount_decrement(&active_cconnects); + isc_test_nap(1); + } + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the TCP client timeouts to 0.05 seconds, connect, + * then sleep for at least a second for each 'tick'. + * timeout_retry_cb() will give up after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* TLS */ + +#if HAVE_LIBNGHTTP2 +static void +tls_connect(isc_nm_t *nm) { + isc_nm_tlsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, tcp_connect_tlsctx, + tcp_tlsctx_client_sess_cache, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(tls_noop) { + stream_use_TLS = true; + stream_noop(state); +} + +ISC_RUN_TEST_IMPL(tls_noresponse) { + stream_use_TLS = true; + stream_noresponse(state); +} + +ISC_RUN_TEST_IMPL(tls_timeout_recovery) { + stream_use_TLS = true; + stream_timeout_recovery(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_one) { + stream_use_TLS = true; + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_two) { + stream_use_TLS = true; + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_half_recv_half_send(state); +} + +/* TLS quota */ + +ISC_RUN_TEST_IMPL(tls_recv_one_quota) { + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_two_quota) { + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} +#endif + +/* TLSDNS */ + +static void +tlsdns_connect(isc_nm_t *nm) { + isc_nm_tlsdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); +} + +ISC_RUN_TEST_IMPL(tlsdns_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + + SKIP_IN_CI; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the TCP client timeouts to 0.05 seconds, connect, + * then sleep for at least a second for each 'tick'. + * timeout_retry_cb() will give up after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 2); + + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +tlsdns_connect_connect_noalpn(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + isc_refcount_decrement(&active_cconnects); + + if (eresult != ISC_R_SUCCESS || connect_readcb == NULL || + isc_nm_xfr_checkperm(handle) != ISC_R_SUCCESS) + { + return; + } + + atomic_fetch_add(&cconnects, 1); + + isc_refcount_increment0(&active_creads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, connect_readcb, NULL); + + connect_send(handle); +} + +ISC_RUN_TEST_IMPL(tlsdns_connect_noalpn) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + isc_tlsctx_t *connect_tlsctx_noalpn = NULL; + + result = isc_tlsctx_createclient(&connect_tlsctx_noalpn); + assert_true(result == ISC_R_SUCCESS); + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + tlsdns_connect_connect_noalpn, NULL, T_CONNECT, 0, + connect_tlsctx_noalpn, NULL); + + WAIT_FOR_EQ(active_cconnects, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); + + isc_tlsctx_free(&connect_tlsctx_noalpn); +} + +#ifdef HAVE_LIBNGHTTP2 + +static isc_result_t +tls_accept_cb_noalpn(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + F(); + + if (eresult != ISC_R_SUCCESS) { + return (eresult); + } + + atomic_fetch_add(&saccepts, 1); + + if (isc_nm_xfr_checkperm(handle) != ISC_R_SUCCESS) { + return (ISC_R_FAILURE); + } + + return (stream_accept_cb(handle, eresult, cbarg)); +} + +ISC_RUN_TEST_IMPL(tlsdns_listen_noalpn) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + isc_tlsctx_t *server_tlsctx_noalpn = NULL; + + result = isc_tlsctx_createserver(NULL, NULL, &server_tlsctx_noalpn); + assert_true(result == ISC_R_SUCCESS); + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + /* We use TLS stream listener here intentionally, as it does not + * try to do ALPN. */ + result = isc_nm_listentls(listen_nm, &tcp_listen_addr, + tls_accept_cb_noalpn, NULL, 0, 0, NULL, + server_tlsctx_noalpn, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(saccepts, 1); + WAIT_FOR_EQ(cconnects, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); + + isc_tlsctx_free(&server_tlsctx_noalpn); +} +#endif /* HAVE_LIBNGHTTP2 */ + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_open, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_bind, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_recv_start, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_open, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_bind, setup_test, teardown_test) +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_connect, setup_test, teardown_test) +#endif +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_recv_buffer_size, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_send_buffer_size, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_half_recv_half_send, setup_test, teardown_test) + +/* TCP */ +ISC_TEST_ENTRY_CUSTOM(tcp_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_sendback, setup_test, + teardown_test) + +/* TCP Quota */ +ISC_TEST_ENTRY_CUSTOM(tcp_recv_one_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_two_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_quota_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_quota_sendback, setup_test, + teardown_test) + +/* TCPDNS */ +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_half_recv_half_send, setup_test, teardown_test) + +#if HAVE_LIBNGHTTP2 +/* TLS */ +ISC_TEST_ENTRY_CUSTOM(tls_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_sendback, setup_test, + teardown_test) + +/* TLS quota */ +ISC_TEST_ENTRY_CUSTOM(tls_recv_one_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_two_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_quota_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_quota_sendback, setup_test, + teardown_test) +#endif + +/* TLSDNS */ +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_connect_noalpn, setup_test, teardown_test) +#ifdef HAVE_LIBNGHTTP2 +ISC_TEST_ENTRY_CUSTOM(tlsdns_listen_noalpn, setup_test, teardown_test) +#endif + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/parse_test.c b/tests/isc/parse_test.c new file mode 100644 index 0000000..a5b516a --- /dev/null +++ b/tests/isc/parse_test.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include + +#include + +/* Test for 32 bit overflow on 64 bit machines in isc_parse_uint32 */ +ISC_RUN_TEST_IMPL(parse_overflow) { + isc_result_t result; + uint32_t output; + + result = isc_parse_uint32(&output, "1234567890", 10); + assert_int_equal(ISC_R_SUCCESS, result); + assert_int_equal(1234567890, output); + + result = isc_parse_uint32(&output, "123456789012345", 10); + assert_int_equal(ISC_R_RANGE, result); + + result = isc_parse_uint32(&output, "12345678901234567890", 10); + assert_int_equal(ISC_R_RANGE, result); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(parse_overflow) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/pool_test.c b/tests/isc/pool_test.c new file mode 100644 index 0000000..35d556f --- /dev/null +++ b/tests/isc/pool_test.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +static isc_result_t +poolinit(void **target, void *arg) { + isc_result_t result; + + isc_taskmgr_t *mgr = (isc_taskmgr_t *)arg; + isc_task_t *task = NULL; + result = isc_task_create(mgr, 0, &task); + if (result != ISC_R_SUCCESS) { + return (result); + } + + *target = (void *)task; + return (ISC_R_SUCCESS); +} + +static void +poolfree(void **target) { + isc_task_t *task = *(isc_task_t **)target; + isc_task_destroy(&task); + *target = NULL; +} + +/* Create a pool */ +ISC_RUN_TEST_IMPL(create_pool) { + isc_result_t result; + isc_pool_t *pool = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 8, poolfree, poolinit, taskmgr, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool), 8); + + isc_pool_destroy(&pool); + assert_null(pool); +} + +/* Resize a pool */ +ISC_RUN_TEST_IMPL(expand_pool) { + isc_result_t result; + isc_pool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 10, poolfree, poolinit, taskmgr, &pool1); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool1), 10); + + /* resizing to a smaller size should have no effect */ + hold = pool1; + result = isc_pool_expand(&pool1, 5, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to the same size should have no effect */ + hold = pool1; + result = isc_pool_expand(&pool1, 10, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to larger size should make a new pool */ + hold = pool1; + result = isc_pool_expand(&pool1, 20, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 20); + assert_ptr_not_equal(pool2, hold); + assert_null(pool1); + + isc_pool_destroy(&pool2); + assert_null(pool2); +} + +/* Get objects */ +ISC_RUN_TEST_IMPL(get_objects) { + isc_result_t result; + isc_pool_t *pool = NULL; + void *item; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 2, poolfree, poolinit, taskmgr, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool), 2); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task1); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task2); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task3); + + isc_task_detach(&task1); + isc_task_detach(&task2); + isc_task_detach(&task3); + + isc_pool_destroy(&pool); + assert_null(pool); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(create_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(expand_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(get_objects, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/quota_test.c b/tests/isc/quota_test.c new file mode 100644 index 0000000..9b202b9 --- /dev/null +++ b/tests/isc/quota_test.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include "netmgr/uv-compat.h" + +#include + +ISC_RUN_TEST_IMPL(isc_quota_get_set) { + UNUSED(state); + isc_quota_t quota; + isc_quota_t *quota2 = NULL; + isc_quota_init("a, 100); + + assert_int_equal(isc_quota_getmax("a), 100); + assert_int_equal(isc_quota_getsoft("a), 0); + + isc_quota_max("a, 50); + isc_quota_soft("a, 30); + + assert_int_equal(isc_quota_getmax("a), 50); + assert_int_equal(isc_quota_getsoft("a), 30); + + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_attach("a, "a2); + assert_int_equal(isc_quota_getused("a), 1); + isc_quota_detach("a2); + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +static void +add_quota(isc_quota_t *source, isc_quota_t **target, + isc_result_t expected_result, int expected_used) { + isc_result_t result; + + *target = NULL; + + result = isc_quota_attach(source, target); + assert_int_equal(result, expected_result); + + switch (expected_result) { + case ISC_R_SUCCESS: + case ISC_R_SOFTQUOTA: + assert_ptr_equal(*target, source); + break; + default: + assert_null(*target); + break; + } + + assert_int_equal(isc_quota_getused(source), expected_used); +} + +ISC_RUN_TEST_IMPL(isc_quota_hard) { + isc_quota_t quota; + isc_quota_t *quotas[110]; + int i; + UNUSED(state); + + isc_quota_init("a, 100); + + for (i = 0; i < 100; i++) { + add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + } + + add_quota("a, "as[100], ISC_R_QUOTA, 100); + + assert_int_equal(isc_quota_getused("a), 100); + + isc_quota_detach("as[0]); + assert_null(quotas[0]); + + add_quota("a, "as[100], ISC_R_SUCCESS, 100); + add_quota("a, "as[101], ISC_R_QUOTA, 100); + + for (i = 100; i > 0; i--) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), i - 1); + } + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +ISC_RUN_TEST_IMPL(isc_quota_soft) { + isc_quota_t quota; + isc_quota_t *quotas[110]; + int i; + UNUSED(state); + + isc_quota_init("a, 100); + isc_quota_soft("a, 50); + + for (i = 0; i < 50; i++) { + add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + } + for (i = 50; i < 100; i++) { + add_quota("a, "as[i], ISC_R_SOFTQUOTA, i + 1); + } + + add_quota("a, "as[i], ISC_R_QUOTA, 100); + + for (i = 99; i >= 0; i--) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), i); + } + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +static atomic_uint_fast32_t cb_calls = 0; +static isc_quota_cb_t cbs[30]; +static isc_quota_t *qp; + +static void +callback(isc_quota_t *quota, void *data) { + int val = *(int *)data; + /* Callback is not called if we get the quota directly */ + assert_int_not_equal(val, -1); + + /* We get the proper quota pointer */ + assert_ptr_equal(quota, qp); + + /* Verify that the callbacks are called in order */ + int v = atomic_fetch_add_relaxed(&cb_calls, 1); + assert_int_equal(v, val); + + /* + * First 5 will be detached by the test function, + * for the last 5 - do a 'chain detach'. + */ + if (v >= 5) { + isc_quota_detach("a); + } +} + +ISC_RUN_TEST_IMPL(isc_quota_callback) { + isc_result_t result; + isc_quota_t quota; + isc_quota_t *quotas[30]; + qp = "a; + /* + * - 10 calls that end with SUCCESS + * - 10 calls that end with SOFTQUOTA + * - 10 callbacks + */ + int ints[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int i; + UNUSED(state); + + isc_quota_init("a, 20); + isc_quota_soft("a, 10); + + for (i = 0; i < 10; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(quotas[i], "a); + assert_int_equal(isc_quota_getused("a), i + 1); + } + for (i = 10; i < 20; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_SOFTQUOTA); + assert_ptr_equal(quotas[i], "a); + assert_int_equal(isc_quota_getused("a), i + 1); + } + + for (i = 20; i < 30; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_QUOTA); + assert_ptr_equal(quotas[i], NULL); + assert_int_equal(isc_quota_getused("a), 20); + } + assert_int_equal(atomic_load(&cb_calls), 0); + + for (i = 0; i < 5; i++) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), 20); + assert_int_equal(atomic_load(&cb_calls), i + 1); + } + /* That should cause a chain reaction */ + isc_quota_detach("as[5]); + assert_int_equal(atomic_load(&cb_calls), 10); + + /* Release the quotas that we did not released in the callback */ + for (i = 0; i < 5; i++) { + qp = "a; + isc_quota_detach(&qp); + } + + for (i = 6; i < 20; i++) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), 19 - i); + } + assert_int_equal(atomic_load(&cb_calls), 10); + + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +/* + * Multithreaded quota callback test: + * - quota set to 100 + * - 10 threads, each trying to get 100 quotas. + * - creates a separate thread to release it after 10ms + */ + +typedef struct qthreadinfo { + atomic_uint_fast32_t direct; + atomic_uint_fast32_t callback; + isc_quota_t *quota; + isc_quota_cb_t callbacks[100]; +} qthreadinfo_t; + +static atomic_uint_fast32_t g_tnum = 0; +/* at most 10 * 100 quota_detach threads */ +isc_thread_t g_threads[10 * 100]; + +static void * +quota_detach(void *quotap) { + isc_quota_t *quota = (isc_quota_t *)quotap; + uv_sleep(10); + isc_quota_detach("a); + return ((isc_threadresult_t)0); +} + +static void +quota_callback(isc_quota_t *quota, void *data) { + qthreadinfo_t *qti = (qthreadinfo_t *)data; + atomic_fetch_add_relaxed(&qti->callback, 1); + int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); + isc_thread_create(quota_detach, quota, &g_threads[tnum]); +} + +static isc_threadresult_t +quota_thread(void *qtip) { + qthreadinfo_t *qti = (qthreadinfo_t *)qtip; + for (int i = 0; i < 100; i++) { + isc_quota_cb_init(&qti->callbacks[i], quota_callback, qti); + isc_quota_t *quota = NULL; + isc_result_t result = isc_quota_attach_cb(qti->quota, "a, + &qti->callbacks[i]); + if (result == ISC_R_SUCCESS) { + atomic_fetch_add_relaxed(&qti->direct, 1); + int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); + isc_thread_create(quota_detach, quota, + &g_threads[tnum]); + } + } + return ((isc_threadresult_t)0); +} + +ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { + UNUSED(state); + isc_quota_t quota; + int i; + + isc_quota_init("a, 100); + static qthreadinfo_t qtis[10]; + isc_thread_t threads[10]; + for (i = 0; i < 10; i++) { + atomic_init(&qtis[i].direct, 0); + atomic_init(&qtis[i].callback, 0); + qtis[i].quota = "a; + isc_thread_create(quota_thread, &qtis[i], &threads[i]); + } + for (i = 0; i < 10; i++) { + isc_thread_join(threads[i], NULL); + } + + for (i = 0; i < (int)atomic_load(&g_tnum); i++) { + isc_thread_join(g_threads[i], NULL); + } + int direct = 0, ncallback = 0; + + for (i = 0; i < 10; i++) { + direct += atomic_load(&qtis[i].direct); + ncallback += atomic_load(&qtis[i].callback); + } + /* Total quota gained must be 10 threads * 100 tries */ + assert_int_equal(direct + ncallback, 10 * 100); + /* + * At least 100 must be direct, the rest is virtually random: + * - in a regular run I'm constantly getting 100:900 ratio + * - under rr - usually around ~120:880 + * - under rr -h - 1000:0 + */ + assert_true(direct >= 100); + + isc_quota_destroy("a); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_quota_get_set) +ISC_TEST_ENTRY(isc_quota_hard) +ISC_TEST_ENTRY(isc_quota_soft) +ISC_TEST_ENTRY(isc_quota_callback) +ISC_TEST_ENTRY(isc_quota_callback_mt) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/radix_test.c b/tests/isc/radix_test.c new file mode 100644 index 0000000..fe589fe --- /dev/null +++ b/tests/isc/radix_test.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include + +#include + +/* test radix node removal */ +ISC_RUN_TEST_IMPL(isc_radix_remove) { + isc_radix_tree_t *radix = NULL; + isc_radix_node_t *node; + isc_prefix_t prefix; + isc_result_t result; + struct in_addr in_addr; + isc_netaddr_t netaddr; + + UNUSED(state); + + result = isc_radix_create(mctx, &radix, 32); + assert_int_equal(result, ISC_R_SUCCESS); + + in_addr.s_addr = inet_addr("1.1.1.1"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 32); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)32; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("1.0.0.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 8); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)8; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("1.1.1.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 24); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)24; + isc_refcount_destroy(&prefix.refcount); + + isc_radix_remove(radix, node); + + isc_radix_destroy(radix, NULL); +} + +/* test radix searching */ +ISC_RUN_TEST_IMPL(isc_radix_search) { + isc_radix_tree_t *radix = NULL; + isc_radix_node_t *node; + isc_prefix_t prefix; + isc_result_t result; + struct in_addr in_addr; + isc_netaddr_t netaddr; + + UNUSED(state); + + result = isc_radix_create(mctx, &radix, 32); + assert_int_equal(result, ISC_R_SUCCESS); + + in_addr.s_addr = inet_addr("3.3.3.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 24); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)1; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("3.3.0.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 16); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)2; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("3.3.3.3"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 22); + + node = NULL; + result = isc_radix_search(radix, &node, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(node->data[0], (void *)2); + + isc_refcount_destroy(&prefix.refcount); + + isc_radix_destroy(radix, NULL); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_radix_remove) +ISC_TEST_ENTRY(isc_radix_search) + +ISC_TEST_LIST_END +ISC_TEST_MAIN diff --git a/tests/isc/random_test.c b/tests/isc/random_test.c new file mode 100644 index 0000000..1935846 --- /dev/null +++ b/tests/isc/random_test.c @@ -0,0 +1,787 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * IMPORTANT NOTE: + * These tests work by generating a large number of pseudo-random numbers + * and then statistically analyzing them to determine whether they seem + * random. The test is expected to fail on occasion by random happenstance. + */ + +#include +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define REPS 25000 + +typedef double(pvalue_func_t)(uint16_t *values, size_t length); + +/* igamc(), igam(), etc. were adapted (and cleaned up) from the Cephes + * math library: + * + * Cephes Math Library Release 2.8: June, 2000 + * Copyright 1985, 1987, 2000 by Stephen L. Moshier + * + * The Cephes math library was released into the public domain as part + * of netlib. + */ + +static double MACHEP = 1.11022302462515654042E-16; +static double MAXLOG = 7.09782712893383996843E2; +static double big = 4.503599627370496e15; +static double biginv = 2.22044604925031308085e-16; + +static double +igamc(double a, double x); +static double +igam(double a, double x); + +typedef enum { + ISC_RANDOM8, + ISC_RANDOM16, + ISC_RANDOM32, + ISC_RANDOM_BYTES, + ISC_RANDOM_UNIFORM, + ISC_NONCE_BYTES +} isc_random_func; + +static double +igamc(double a, double x) { + double ans, ax, c, r, t, y, z; + double pkm1, pkm2, qkm1, qkm2; + + if ((x <= 0) || (a <= 0)) { + return (1.0); + } + + if ((x < 1.0) || (x < a)) { + return (1.0 - igam(a, x)); + } + + ax = a * log(x) - x - lgamma(a); + if (ax < -MAXLOG) { + print_error("# igamc: UNDERFLOW, ax=%f\n", ax); + return (0.0); + } + ax = exp(ax); + + /* continued fraction */ + y = 1.0 - a; + z = x + y + 1.0; + c = 0.0; + pkm2 = 1.0; + qkm2 = x; + pkm1 = x + 1.0; + qkm1 = z * x; + ans = pkm1 / qkm1; + + do { + double yc, pk, qk; + c += 1.0; + y += 1.0; + z += 2.0; + yc = y * c; + pk = pkm1 * z - pkm2 * yc; + qk = qkm1 * z - qkm2 * yc; + if (qk != 0) { + r = pk / qk; + t = fabs((ans - r) / r); + ans = r; + } else { + t = 1.0; + } + + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if (fabs(pk) > big) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + } while (t > MACHEP); + + return (ans * ax); +} + +static double +igam(double a, double x) { + double ans, ax, c, r; + + if ((x <= 0) || (a <= 0)) { + return (0.0); + } + + if ((x > 1.0) && (x > a)) { + return (1.0 - igamc(a, x)); + } + + /* Compute x**a * exp(-x) / md_gamma(a) */ + ax = a * log(x) - x - lgamma(a); + if (ax < -MAXLOG) { + print_error("# igam: UNDERFLOW, ax=%f\n", ax); + return (0.0); + } + ax = exp(ax); + + /* power series */ + r = a; + c = 1.0; + ans = 1.0; + + do { + r += 1.0; + c *= x / r; + ans += c; + } while (c / ans > MACHEP); + + return (ans * ax / a); +} + +static int8_t scounts_table[65536]; +static uint8_t bitcounts_table[65536]; + +static int8_t +scount_calculate(uint16_t n) { + int i; + int8_t sc; + + sc = 0; + for (i = 0; i < 16; i++) { + uint16_t lsb; + + lsb = n & 1; + if (lsb != 0) { + sc += 1; + } else { + sc -= 1; + } + + n >>= 1; + } + + return (sc); +} + +static uint8_t +bitcount_calculate(uint16_t n) { + int i; + uint8_t bc; + + bc = 0; + for (i = 0; i < 16; i++) { + uint16_t lsb; + + lsb = n & 1; + if (lsb != 0) { + bc += 1; + } + + n >>= 1; + } + + return (bc); +} + +static void +tables_init(void) { + uint32_t i; + + for (i = 0; i < 65536; i++) { + scounts_table[i] = scount_calculate(i); + bitcounts_table[i] = bitcount_calculate(i); + } +} + +/* + * The following code for computing Marsaglia's rank is based on the + * implementation in cdbinrnk.c from the diehard tests by George + * Marsaglia. + * + * This function destroys (modifies) the data passed in bits. + */ +static uint32_t +matrix_binaryrank(uint32_t *bits, size_t rows, size_t cols) { + unsigned int rt = 0; + uint32_t rank = 0; + uint32_t tmp; + + for (size_t k = 0; k < rows; k++) { + size_t i = k; + + while (rt >= cols || ((bits[i] >> rt) & 1) == 0) { + i++; + + if (i < rows) { + continue; + } else { + rt++; + if (rt < cols) { + i = k; + continue; + } + } + + return (rank); + } + + rank++; + if (i != k) { + tmp = bits[i]; + bits[i] = bits[k]; + bits[k] = tmp; + } + + for (size_t j = i + 1; j < rows; j++) { + if (((bits[j] >> rt) & 1) == 0) { + continue; + } else { + bits[j] ^= bits[k]; + } + } + + rt++; + } + + return (rank); +} + +static void +random_test(pvalue_func_t *func, isc_random_func test_func) { + uint32_t m; + uint32_t j; + uint32_t histogram[11] = { 0 }; + uint32_t passed; + double proportion; + double p_hat; + double lower_confidence, higher_confidence; + double chi_square; + double p_value_t; + double alpha; + + tables_init(); + + m = 1000; + passed = 0; + + for (j = 0; j < m; j++) { + uint32_t i; + uint32_t values[REPS]; + uint16_t *uniform_values; + double p_value; + + switch (test_func) { + case ISC_RANDOM8: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random8(); + } + break; + case ISC_RANDOM16: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random16(); + } + break; + case ISC_RANDOM32: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random32(); + } + break; + case ISC_RANDOM_BYTES: + isc_random_buf(values, sizeof(values)); + break; + case ISC_RANDOM_UNIFORM: + uniform_values = (uint16_t *)values; + for (i = 0; + i < (sizeof(values) / (sizeof(*uniform_values))); + i++) + { + uniform_values[i] = + isc_random_uniform(UINT16_MAX); + } + break; + case ISC_NONCE_BYTES: + isc_nonce_buf(values, sizeof(values)); + break; + } + + p_value = (*func)((uint16_t *)values, REPS * 2); + if (p_value >= 0.01) { + passed++; + } + + assert_in_range(p_value, 0.0, 1.0); + + i = (int)floor(p_value * 10); + histogram[i]++; + } + + /* + * Check proportion of sequences passing a test (see section + * 4.2.1 in NIST SP 800-22). + */ + alpha = 0.01; /* the significance level */ + proportion = (double)passed / (double)m; + p_hat = 1.0 - alpha; + lower_confidence = p_hat - (3.0 * sqrt((p_hat * (1.0 - p_hat)) / m)); + higher_confidence = p_hat + (3.0 * sqrt((p_hat * (1.0 - p_hat)) / m)); + + assert_in_range(proportion, lower_confidence, higher_confidence); + + /* + * Check uniform distribution of p-values (see section 4.2.2 in + * NIST SP 800-22). + */ + + /* Fold histogram[10] (p_value = 1.0) into histogram[9] for + * interval [0.9, 1.0] + */ + histogram[9] += histogram[10]; + histogram[10] = 0; + + /* Pre-requisite that at least 55 sequences are processed. */ + assert_true(m >= 55); + + chi_square = 0.0; + for (j = 0; j < 10; j++) { + double numer; + double denom; + + numer = (histogram[j] - (m / 10.0)) * + (histogram[j] - (m / 10.0)); + denom = m / 10.0; + chi_square += numer / denom; + } + + p_value_t = igamc(9 / 2.0, chi_square / 2.0); + + assert_true(p_value_t >= 0.0001); +} + +/* + * This is a frequency (monobits) test taken from the NIST SP 800-22 + * RANDOM test suite. + */ +static double +monobit(uint16_t *values, size_t length) { + size_t i; + int32_t scount; + uint32_t numbits; + double s_obs; + double p_value; + + UNUSED(mctx); + + numbits = length * sizeof(*values) * 8; + scount = 0; + + for (i = 0; i < length; i++) { + scount += scounts_table[values[i]]; + } + + /* Preconditions (section 2.1.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + + s_obs = abs(scount) / sqrt(numbits); + p_value = erfc(s_obs / sqrt(2.0)); + + return (p_value); +} + +/* + * This is the runs test taken from the NIST SP 800-22 RNG test suite. + */ +static double +runs(uint16_t *values, size_t length) { + size_t i; + uint32_t bcount; + uint32_t numbits; + double pi; + double tau; + uint32_t j; + uint32_t b; + uint8_t bit_prev; + uint32_t v_obs; + double numer; + double denom; + double p_value; + + UNUSED(mctx); + + numbits = length * sizeof(*values) * 8; + bcount = 0; + + for (i = 0; i < length; i++) { + bcount += bitcounts_table[values[i]]; + } + + pi = (double)bcount / (double)numbits; + tau = 2.0 / sqrt(numbits); + + /* Preconditions (section 2.3.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + + /* + * Pre-condition implied from the monobit test. This can fail + * for some sequences, and the p-value is taken as 0 in these + * cases. + */ + if (fabs(pi - 0.5) >= tau) { + return (0.0); + } + + /* Compute v_obs */ + j = 0; + b = 14; + bit_prev = (values[j] & (1U << 15)) == 0 ? 0 : 1; + + v_obs = 0; + + for (i = 1; i < numbits; i++) { + uint8_t bit_this = (values[j] & (1U << b)) == 0 ? 0 : 1; + if (b == 0) { + b = 15; + j++; + } else { + b--; + } + + v_obs += bit_this ^ bit_prev; + + bit_prev = bit_this; + } + + v_obs += 1; + + numer = fabs(v_obs - (2.0 * numbits * pi * (1.0 - pi))); + denom = 2.0 * sqrt(2.0 * numbits) * pi * (1.0 - pi); + + p_value = erfc(numer / denom); + + return (p_value); +} + +/* + * This is the block frequency test taken from the NIST SP 800-22 RNG + * test suite. + */ +static double +blockfrequency(uint16_t *values, size_t length) { + uint32_t i; + uint32_t numbits; + uint32_t mbits; + uint32_t mwords; + uint32_t numblocks; + double *pi; + double chi_square; + double p_value; + + numbits = length * sizeof(*values) * 8; + mbits = 32000; + mwords = mbits / 16; + numblocks = numbits / mbits; + + /* Preconditions (section 2.2.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + assert_true(mbits >= 20); + assert_true((double)mbits > (0.01 * numbits)); + assert_true(numblocks < 100); + assert_true(numbits >= (mbits * numblocks)); + + pi = isc_mem_get(mctx, numblocks * sizeof(double)); + assert_non_null(pi); + + for (i = 0; i < numblocks; i++) { + uint32_t j; + pi[i] = 0.0; + for (j = 0; j < mwords; j++) { + uint32_t idx; + + idx = i * mwords + j; + pi[i] += bitcounts_table[values[idx]]; + } + pi[i] /= mbits; + } + + /* Compute chi_square */ + chi_square = 0.0; + for (i = 0; i < numblocks; i++) { + chi_square += (pi[i] - 0.5) * (pi[i] - 0.5); + } + + chi_square *= 4 * mbits; + + isc_mem_put(mctx, pi, numblocks * sizeof(double)); + + p_value = igamc(numblocks * 0.5, chi_square * 0.5); + + return (p_value); +} + +/* + * This is the binary matrix rank test taken from the NIST SP 800-22 RNG + * test suite. + */ +static double +binarymatrixrank(uint16_t *values, size_t length) { + uint32_t i; + size_t matrix_m; + size_t matrix_q; + uint32_t num_matrices; + size_t numbits; + uint32_t fm_0; + uint32_t fm_1; + uint32_t fm_rest; + double term1; + double term2; + double term3; + double chi_square; + double p_value; + + UNUSED(mctx); + + matrix_m = 32; + matrix_q = 32; + num_matrices = length / ((matrix_m * matrix_q) / 16); + numbits = num_matrices * matrix_m * matrix_q; + + /* Preconditions (section 2.5.7 in NIST SP 800-22) */ + assert_int_equal(matrix_m, 32); + assert_int_equal(matrix_q, 32); + assert_true(numbits >= (38 * matrix_m * matrix_q)); + + fm_0 = 0; + fm_1 = 0; + fm_rest = 0; + for (i = 0; i < num_matrices; i++) { + /* + * Each uint32_t supplies 32 bits, so a 32x32 bit matrix + * takes up uint32_t array of size 32. + */ + uint32_t bits[32]; + int j; + uint32_t rank; + + for (j = 0; j < 32; j++) { + size_t idx; + uint32_t r1; + uint32_t r2; + + idx = i * ((matrix_m * matrix_q) / 16); + idx += j * 2; + + r1 = values[idx]; + r2 = values[idx + 1]; + bits[j] = (r1 << 16) | r2; + } + + rank = matrix_binaryrank(bits, matrix_m, matrix_q); + + if (rank == matrix_m) { + fm_0++; + } else if (rank == (matrix_m - 1)) { + fm_1++; + } else { + fm_rest++; + } + } + + /* Compute chi_square */ + term1 = ((fm_0 - (0.2888 * num_matrices)) * + (fm_0 - (0.2888 * num_matrices))) / + (0.2888 * num_matrices); + term2 = ((fm_1 - (0.5776 * num_matrices)) * + (fm_1 - (0.5776 * num_matrices))) / + (0.5776 * num_matrices); + term3 = ((fm_rest - (0.1336 * num_matrices)) * + (fm_rest - (0.1336 * num_matrices))) / + (0.1336 * num_matrices); + + chi_square = term1 + term2 + term3; + + p_value = exp(-chi_square * 0.5); + + return (p_value); +} + +/*** + *** Tests for isc_random32() function + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM32); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM32); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM32); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM32); +} + +/*** + *** Tests for isc_random_bytes() function + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM_BYTES); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM_BYTES); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM_BYTES); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM_BYTES); +} + +/*** + *** Tests for isc_random_uniform() function: + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM_UNIFORM); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM_UNIFORM); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM_UNIFORM); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM_UNIFORM); +} + +/* Tests for isc_nonce_bytes() function */ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_monobit) { + UNUSED(state); + + random_test(monobit, ISC_NONCE_BYTES); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_runs) { + UNUSED(state); + + random_test(runs, ISC_NONCE_BYTES); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_NONCE_BYTES); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_NONCE_BYTES); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_random32_monobit) +ISC_TEST_ENTRY(isc_random32_runs) +ISC_TEST_ENTRY(isc_random32_blockfrequency) +ISC_TEST_ENTRY(isc_random32_binarymatrixrank) +ISC_TEST_ENTRY(isc_random_bytes_monobit) +ISC_TEST_ENTRY(isc_random_bytes_runs) +ISC_TEST_ENTRY(isc_random_bytes_blockfrequency) +ISC_TEST_ENTRY(isc_random_bytes_binarymatrixrank) +ISC_TEST_ENTRY(isc_random_uniform_monobit) +ISC_TEST_ENTRY(isc_random_uniform_runs) +ISC_TEST_ENTRY(isc_random_uniform_blockfrequency) +ISC_TEST_ENTRY(isc_random_uniform_binarymatrixrank) +ISC_TEST_ENTRY(isc_nonce_bytes_monobit) +ISC_TEST_ENTRY(isc_nonce_bytes_runs) +ISC_TEST_ENTRY(isc_nonce_bytes_blockfrequency) +ISC_TEST_ENTRY(isc_nonce_bytes_binarymatrixrank) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/regex_test.c b/tests/isc/regex_test.c new file mode 100644 index 0000000..12051f1 --- /dev/null +++ b/tests/isc/regex_test.c @@ -0,0 +1,2335 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_REGEX_H +#include +#endif /* ifdef HAVE_REGEX_H */ + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include + +/* test isc_regex_validate() */ +ISC_RUN_TEST_IMPL(regex_validate) { + /* + * test regex were generated using http://code.google.com/p/regfuzz/ + * modified to use only printable characters + */ + struct { + const char *expression; + int expect; + int exception; /* regcomp accepts but is + * disallowed. */ + } tests[] = { + { "", -1, 0 }, + { "*", -1, 0 }, + { ".*", 0, 0 }, + { ".**", -1, 0 }, + { ".*\?", -1, 0 }, + { ".*+", -1, 0 }, + { "+", -1, 0 }, + { ".+", 0, 0 }, + { ".++", -1, 0 }, + { ".+\?", -1, 0 }, + { ".+*", -1, 0 }, + { "\?", -1, 0 }, + { ".\?", 0, 0 }, + { ".\?\?", -1, 0 }, + { ".\?*", -1, 0 }, + { ".\?+", -1, 0 }, + { "(", -1, 0 }, + { "()", 1, 0 }, + { "(|)", -1, 0 }, + { "(a|)", -1, 0 }, + { "(|b)", -1, 0 }, + { ".{", 0, 0 }, + { ".{1", -1, 0 }, + { ".\\{1", 0, 0 }, + { ".{1}", 0, 0 }, + { ".\\{1}", 0, 0 }, + { ".{,", 0, 0 }, + { ".{,}", 0, 0 }, + { ".{1,}", 0, 0 }, + { ".\\{1,}", 0, 0 }, + { ".{1,\\}", -1, 0 }, + { ".{1,", -1, 0 }, + { ".\\{1,", 0, 0 }, + { ".{1,2}", 0, 0 }, + { ".{1,2}*", -1, 0 }, + { ".{1,2}+", -1, 0 }, + { ".{1,2}\?", -1, 0 }, + { ".{1,2", -1, 0 }, + { ".{2,1}", -1, 0 }, + { "[", -1, 0 }, + { "[]", -1, 0 }, + { "[]]", 0, 0 }, + { "[[]", 0, 0 }, + { "[^]", -1, 0 }, + { "[1-2-3]", -1, 0 }, + { "[1-22-3]", 0, 0 }, + { "[+--23]", 0, 0 }, + { "[+--]", 0, 0 }, + { "[-1]", 0, 0 }, + { "[1-]", 0, 0 }, + { "[[.^.]]", 0, 0 }, + { "[^]]", 0, 0 }, + { "[^^]", 0, 0 }, + { "[]]\?", 0, 0 }, + { "[[]\?", 0, 0 }, + { "[[..]]", -1, 0 }, + { "[[...]]", 0, 0 }, + { "[[..5.]--]", -1, 0 }, + { "[[.+.]--]", 0, 0 }, + { "[[..+.]--]", -1, 0 }, + { "[[.5.]--]", -1, 0 }, + { "[1-[=x=]]", -1, 0 }, + { "[[:alpha:]]", 0, 0 }, + { "[[:alpha:]", -1, 0 }, + { "[[:alnum:]]", 0, 0 }, + { "[[:alnum:]", -1, 0 }, + { "[[:digit:]]", 0, 0 }, + { "[[:digit:]", -1, 0 }, + { "[[:punct:]]", 0, 0 }, + { "[[:punct:]", -1, 0 }, + { "[[:graph:]]", 0, 0 }, + { "[[:graph:]", -1, 0 }, + { "[[:space:]]", 0, 0 }, + { "[[:space:]", -1, 0 }, + { "[[:blank:]]", 0, 0 }, + { "[[:blank:]", -1, 0 }, + { "[[:upper:]]", 0, 0 }, + { "[[:upper:]", -1, 0 }, + { "[[:cntrl:]]", 0, 0 }, + { "[[:cntrl:]", -1, 0 }, + { "[[:print:]]", 0, 0 }, + { "[[:print:]", -1, 0 }, + { "[[:xdigit:]]", 0, 0 }, + { "[[:xdigit:]", -1, 0 }, + { "[[:unknown:]]", -1, 0 }, + { "\\[", 0, 0 }, + { "(a)\\1", 1, 0 }, + { "(a)\\2", -1, 1 }, + { "\\0", 0, 0 }, + { "[[][:g(\?(raph:][:alnu)(\?{m:][:space:]h]/" + "r(\?<(\?=!(\?(\?!Nn(\?#])))", 0, 0 }, + { "[(\?!(\?<=[^{,37}AAAA(AAAAAAAAAAAAA])", 0, 0 }, + { "[^((\?(\?:ms(\?\?=[])p.]}8X[:blankcntrl:],{-119,94})XmF1.{)-)" + "[:upperword:])[:digit:]{zg-q", + 2, 0 }, + { "[^[({(\?#254}))Z[l][x50]=444444444444(4444444444u[:punct:]" + "\?[:punct:(\?!])])", + 1, 0 }, + { "[^[^[^([^((*4[(^((\?<=])Ec)", 0, 0 }, + { "(0)Y:8biiiiiiiiiiiiiiiiiii", 1, 0 }, + { "[^w(\?!)P::::::::::::::(\?#::(\?<=:::::::::]\"\"{}[" + "3333333333333333(\?<=33333(\?!)9Xja][:alph(\?<=a:])xB1)(" + "PX8Cf\?4444)qq[:digit:])", + 1, 0 }, + { "([U[^[^].]^m]/306KS7JJJJJJJJ{})", 1, 0 }, + { "[^[^([^[(\?!(\?>8j`Wg2(\?{,(\?>!#N++++(\?@+(\?>l.]}))*\\BCYX]^W{52,123}(" + "lXislccccccccccccccccc)-*)", + 1, 0 }, + { "(x42+,)7=]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", 1, 0 }, + { "[^(*[:graph:]q/TH\?B(\?{P)]})uZn[:digit:]+2", 0, 0 }, + { "([XXXXXXXXXXXXXXXXXXXXX[(:alnum:][:space:]i%[:upperw(\?=o(" + "\?#rd:])) ", + 1, 0 }, + { "(@@@@)", 1, 0 }, + { "{-18,}[:as[(\?>^[cii:]]{}>+{-46,}{,95}[:punct:]{}" + "99999999999999])-{-134}'sK$" + "wCKjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj", + 0, 0 }, + { "(l[:alpha:(\?!]))", 1, 0 }, + { "[[^(\?{]|JJ[:alph(a:]X{})B^][:lowerprint:]n-219{-32}{19,105}" + "k4P}){,-144}", + 0, 0 }, + { "[[^]P[:punct:][:alpha:][:xdigit:]syh]|W#JS*(m<2,P-RK)cA@", 1, + 0 }, + { "([^((\?({\?<=)}){[^}^]{}])^P4[:punct:[]$)]", 1, 0 }, + { "([(\?#:(\?{space:]}):{}{-242,}n)F[:alpha:]3$)d4H3up6qS[:" + "blankcntrl:]B:C{}[:upperword:]r", + 1, 0 }, + { "([(\?:]))[:digit:]mLV.{}", 1, 0 }, + { "[^PPP-[]{[,50}{128,}]111111111111111]p", 0, 0 }, + { "[^([^([^([[^[([^[^[[2[[[[[[[[[[[[[^[[[[(\?(\?{:[[[[[[(\?([-[" + ":ascii:]--*)", + -1, 0 }, + { ")!F^DA/ZZZZZZZZZZZZZZZZZZ", 0, 0 }, + { "[[[[[[[((\?=\?(\?>([[[[[[[^[[[[(\?()[[[K(\?#))])))]7Y[:" + "space:]{,-96}pP)[:ascii:]u{-88}:N{-251}uo", + 0, 0 }, + { "t[:x(\?<=digit:])eYYYYYYYYYYYYYYYYYY{,-220}A", 0, 0 }, + { "[[({10,}[:graph:]Pdddddd(\?#X)])[:alnum:(]]L-C){,50}[:" + "blankcntrl:]p[:gra(ph:]){66,}", + 0, 0 }, + { "[^[^]*4br]w[:digit(\?::]n99999999999999999)P[:punct:]pP", 0, + 0 }, + { "[:digit:]{67,247}!N{122})VrXe", 0, 0 }, + { "[:xdigit:]^[:xdigit:]Z[:alnum:]^^^^1[:upperword:(\?=])[:" + "lowerprint:]*JJ-", + 0, 0 }, + { "[[(\?imsximsx:^*e(){,3[6}](V~\?^[:asc(\?!ii:]I.dZ))]$^" + "AAAAAAAAAAAAAAAAAAAAAAAA[:space:]k)]", + 1, 0 }, + { "W{,112}[:lowerp(\?R7~t'" + "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"9,O).", + 0, 0 }, + { "[^{6((\?>\?:4}(\?<=G))f)" + "KKKKKKKKKKKKKKKKKKKKKKKKKKKKKpppppppp(\?=ppppp]{,-101}|[:" + "blankcntrl:]Z{-182})", + 0, 0 }, + { "([:punct:]@^,,,,,,,,,,,,,,,,,,,,,,,,,,0\?:-o8NPIIIIIIIII)" + "pPKKKKKKKKKKKKKKKKKKKK", + 1, 0 }, + { "([^[[^[^]]]])", 1, 0 }, + { "[([^[(333\"(\?#\\\\[)(\?isx-x:\"Tx]')", 0, 0 }, + { "[[n>^>T%.zzzzzzzzzzzzzzzzz$&|Fk.1o7^o, " + "^8{202,-12}$[:alnum:]]G[:upperword:]V[:xdigit:]L|[:" + "upperword:]KKKKKKKKKKKKYX\"\")xJ " + "~B@[{,-68}/][:upperword:]QI.", + 0, 0 }, + { "[^[]tN^hy3\"d@v T[GE\?^~{124,10(\?{2}]})\?[:upperword:]O", 0, + 0 }, + { "d.``````````````````````````[:up(\?=perword:]" + "RRRRRRRRRRRRRRR)", + 0, 0 }, + { "[Z{{{{{{{{{{{{{(\?={(\?{{J6N:H[tA+mN3Zmf:p\?]" + "\?){-181,82}S4n.b[:lowerpri(\?{nt:]|" + "ggggggggggggggggggggggggggggggg}))4)", + 0, 0 }, + { "[^((/////[^////[^/////////[(^/////]fI{240}{-120}+]R]GA)", 0, + 0 }, + { "[-(\?#.)(\?())[:alpha:](\?={(\?#}r)[:space:]PPW]o)", 0, 0 }, + { "[:lowerp(\?{rint:]})201{46,}[:a[^scii:]0Q{37,}][:blankcntrl:" + "]1331", + 0, 0 }, + { "[^(\?!(\?#)\\GIwxKKKKKKKKKK'$KKKKKKKK]l)bbb^&\?", 0, 0 }, + { "[:ascii:]*[:sp(\?<=ace:])", 0, 0 }, + { "({-66,}Z{})0I{-111,}[:punct(\?():])", 1, 0 }, + { "[[^(\?!()%%%%%%%%%%%%%(\?:%%%%%%%%%%%%%%%%)t(\?{VX>B#6sUU(" + "\?BBBZvvvvvvvvvv(\?m(sximsx:vvv)iiiiiiii)))" + "j>Rs:Sm]0MMMMMMMMMMM|@F)Y]*^#EEEEEEE)*", + 0, 0 }, + { "([^([(U(\?!)<<<<<<<<<<(\?#<<<<(\?(\?#){}]{}`){1,82}){-143[,}]^G", 0, 0 }, + { "[:digit:]W|[:up(\?@]", + 1, 0 }, + { "[^[^[(\?imsximsx::p(\?{unct:][(\?>:ascii:]5w)]{159}\\Q\?@C]" + "4(44444444}[^)|)[:graph:]]C:b)", + 1, 0 }, + { "[^[[(tYri[W<8%1(\?='yt][:lowerprint:[]))1r]][:alnum:][:" + "digit:]{48}{-52,-183}+][:alpha:]r][:upperword:]\?{-105,155}{" + "-55,-87}pPN#############################{63,232}]", + 0, 0 }, + { "[*(\?>L(\?<(\?>=))]&&&&&&&(&&&&&&&&&&&&&&&&&&))[|WIX]{-62,-" + "114}S K=HW60XE<2+W", + 1, 0 }, + { "(00000000000)z\\\\*t{}R{88}[:alnum:]*", 1, 0 }, + { "(([^(\?=\?gggggg[gLw)]{-250,}[:xdigit:]yZ[:g(raph:]8QNr[:" + "space:][:blankcntrl:]A)][:digit:]D)[:xdigit:])", + 2, 0 }, + { "[^([^,(\?s8.>[^{}$(\?(]]XXXXXXX)" + "XXXXXXXXXXXXXX[:alpha:]Whii\?p[:xdigit:])+", + 0, 0 }, + { "(7777[:blankcntrl:])", 1, 0 }, + { "[^C[:digit:]]{}YYYY(YYYYYYYYYYYYYYYY)", 1, 0 }, + { "on|,#tve%F(w-::::::::::::::::::::::::::::*=->)", 1, 0 }, + { "([((\?=(\?!((\?=')))27(<{})S-vvvvvvvvvv(\?=" + "vvvvvvvvvvvvvvvvv[:punct:][:alnum:]}}}}}}}}}}}}}}}}}}}}}}}" + "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPgggggggggggggggggggggggggg(\?#(" + "\?#gggggg+))uQ)W>[:punct:][:xdigit:][:" + "digit:][:punct:]{}[:digit:][:space:]){,-105}=xiAyf}o[:alpha:" + "]akZSYK+sl{", + 1, 0 }, + { "[^[^]/S:Hq<[:upperword:(\?<=]W[:alnum:]X])1973", 0, 0 }, + { "[[^[[^([^VVVV(\?!(VVVVVVVVVVVVVVVVVVVVV[VVVVX][^]2))" + "98ppppppppppppppppppppppppppppppp/////////////////////" + "b.]G{-101,}[:[ascii:]P].=~])AAAAAAAAAAAAA2{-153,}]]]]]]]]]]]" + "]]]]]]]]]]]]]]]]]]]]][:alnum:][:lowerprint:]WN/" + "D!rD]|4444{180}]V_@3lW#lat]", + 0, 0 }, + { "[^[^([^TTTTT(\?:T(\?:T7777{,59}])[:graph:][:ascii(\?<=:]))f]" + "AD{,-43}%%%%%%%%%%%%%%%%)S|[:digit:]FZm<[:blankcntrl:]QT&xj*" + "{-114,}$[:xdigit:]042][:xdig[it:]{-180}027[:alpha:][:ascii:]" + "[:lowerprint:][:xdigit:]^|[:alnum:][^Mi]z!suQ{-44,-32}[:" + "digit:]]", + 0, 0 }, + { ")", 0, 0 }, + { "''''''''''[:a(\?imsxisx:lnum:])P", 0, 0 }, + { "(([{20(\?<=8}[:alnum:]pP$`(\?#N)wRH[:graph:]aaaaaaaaaaaaaa(" + "\?=aaaaaaaaaaaaaaaaP]a)))[:punct:]-\?)A^", + 2, 0 }, + { "[^(.//" + "[:punct:]&-333333333333333333333333333(\?W90DDDDDDDDDDD[^" + "DDDDDDDDDDDDDDDDDDDD]B[:punct:]c/", + 1, 0 }, + { "[^(\?]|)" + "p1EmmmmmmmmmmmmmmmmmmmmmmmmmmmmL{-241}666666666666666666666)" + "]^bLDDDDDDDDDDDDD]", + 0, 0 }, + { "[nn(\?1((\?>\?#45)Z{,108}{}11111111111111111111111111qqqq)" + "\?][:lowerprint:]mbo#)@", + 0, 0 }, + { "[^iii8(888888(\?(\?=)]]T()[:bl(\?!ankcntrl:]=jjjjjjjjjjjjjjjj-" + ")))t{}[:alpha:]-\":i! Gn[A4Ym7<<<<<<<<<<<<<<<<]", + 2, 0 }, + { "^{}{[^,241(\?#}(\?m(\?ixim:sximsx:]t))+oD)", 0, 0 }, + { "5[(\?#:xdigit:])", 0, 0 }, + { "[^f{(\?>,22(9}[^[^])6KKKKKKKKKKKKK)]RRRRRRRRfuK99999999C}" + "osnNR]BgCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[:blankcntrl:]", + 0, 0 }, + { "[^(\?=U){24,}W-{,17(\?:3[^}]q.nQ#PU_|i$$$$$$$$$$$$$$+)[:dig(" + "\?4^4ta[:alpha:]", + 0, 0 }, + { "(((b0HN)q))p5X)uH]$})354b[:alnum:" + "]]]EVVVVVVVVVVVVVVVVVVVVVVVVVVVVVz[:digi(\?(t:][:upperword:]" + ")", + 1, 0 }, + { "([:blankcntrl:]t-){121,}[:ascii:]444444{}[:graph:]E040", 1, + 0 }, + { "[^{134,}]DzQ\?{-30,191})z,\?1Vfq!z}cgv)ERK)1T/=f\?>'", 0, + 0 }, + { "@v)))])Y]|){,10}\?{}", 0, + 0 }, + { "([[[(\?!^]P-AA[AAAAAA[A[^A)r]+B]])", 1, 0 }, + { "3}|[:ascii:][:punct:]()", 1, 0 }, + { "()dw", 1, 0 }, + { "[N]{})))))))))))))))))))))))", 0, 0 }, + { "[[[^([[(\?()(\?#)++([^\?{+++[^+++++++++++(\?!+(\?=+++++++r9/" + "n]N7{-219}{-91}pP[:punct:]T]mROm+~[:digit:][:digit:])Y:", + 0, 0 }, + { "[^'Pu[(\?~\?N|z#Ar--SO{,-" + "141}076)G\?{,-110}M+-[:alpha:]", + 0, 0 }, + { "{,-214}{,10(9})", 1, 0 }, + { "([^xxxxxxxxxxxxxxxxxMMMMMMMMMMMMMMXW])].[:punct:]Q`{-63,63}" + "Uua[:alnum:]\?OQssb#L@@@@@@@@(@@@)[:graph:]", + 2, 0 }, + { "[[^(\?!```[^``````````````(\?<=``(\?>````````M/////(\?!/////" + "///////////////" + "[^GD!|#li]~)*.$]))Tq!]C[:lowerprint:]Qk[{}]]" + "JJJJJJJJJJJJJJJJJJJJJJJ{e])c", + 0, 0 }, + { "$[5(7ES])[:xdigit:]%{MRMtYD&aS&g6jp&ghJ@:!I~4%{" + "P\?0vvvvvvvvvvvvvvvvvvvv\\\\\\\\\\\\\\\\\\\\\\\\x54[:" + "lowerprint:][:upperword:]", + 0, 0 }, + { "[((([(\?((\?>[:alnum:][):as(\?{,-49})q${98,}J\?]){", + 0, 0 }, + { "([:pu(\?(nc)t:]F{-32,-102}+)\?cpP[:lowerprint:].^)", 1, 0 }, + { "([{}{210,-238}]1:h)", 1, 0 }, + { "([]QQQQ[QQQQQQQQQQQQQQQQQQ][:digit:]Z{-20,}Slllllll[:space:]" + "C^(@{-174,-156}fx{cf2c}{-242,}rBBBBBBBBBBBBBBBBBBc[:alpha:]" + "N\?))$[:graph:][:ascii:]P+nnnnnnnnnnnnnnnnnnnnnnn1N$r>>>>>>>" + ">>>>>>>>>>>>>>>>>(>>{,88}{,-234}__________)[:upperword:]R.[:" + "alnum:][:lowerprint:]^}\"", + 3, 0 }, + { "([^(\?=]-))$", 1, 0 }, + { "([:ascii:]\?,D[:upperword:][:xdigit:]tttttttttttt[^tt(\?{,10}[(\?<=:xdigit:]))PL9{-89,-181}F'''''''''", 1, + 0 }, + { "[^.|(\?{af]})^$XE!$", 0, 0 }, + { "(WWWWWWWWWWWWWWWWWWWWWWWWWWWW#J)", 1, 0 }, + { "({}}M7we-216)L[:digit:][:upperword:]", 1, 0 }, + { "([:aln[^u(\?=m:]))].z", 1, 0 }, + { "([:alpha:]{(92})%6{41,136})Vij@[:alnum:][:lowerprint:]", 2, + 0 }, + { "[[[++(\?{+++{}})n{{137,}{51,-177}Z[]M*[:ascii:]{(-29,-47}2)$" + "e^{,-195}{-156,}^]{}{-225,69}A]{-222,}{,20}m[:blankcntrl:]", + 1, 0 }, + { ")l)[:alnum:][:graph:]g8TTTTTTTTTTTTTTTTLLLLLLLLLLLLLLLLL", 0, + 0 }, + { "[([(\?<=.(\?{)/})mmmmmmmm(\?(mmmmm]{-154,-176}*S)I]", 0, 0 }, + { "[(([{(\?(\?[:lowerprint:][:" + "ascii:]e-]]]]]]]]]]]]]]]]]]]]]", + 0, 0 }, + { "[^({}(){(66(\?=,}[^]'''''QQQQQQQQQ).P#>^){86,168}Z[(\?Q{,147}_____________(\?!______uuuuuuuuuuuuuTr]){74,179}" + "{}){,103}{-209,16}*RRRRRRRRRRRRRRRRw{,87}9{144}[:ascii:]'<" + "Ab", + 0, 0 }, + { "([666c] {-171}yc,8-k_)EEEEEEEEEEEEEEEEEEEEE<", 1, 0 }, + { "[^(\?>(\?raph:])^)Ny6RF_ndoU9@*rxW{4,41}4{}", + 0, 0 }, + { "[:punct:]{162,}j[:aln(um:].....................[^...]\?>z[:" + "l[owerprint:]){55,222}]", + 0, 0 }, + { "(>vWa)OXcccccccccccccccccccccccc[:alpha:]C{,-10}81|m1D^T)[:" + "lowerprint:]''''[:alpha:]l", + 1, 0 }, + { "(XZcgM/UI-/" + "mZq-222){-85,-196}[:alpha:]{114}rrrrrrrrrrrrrrrrrrrrrrrr{," + "157}ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZLkD-&&&&&&&&&&&&&&&-][:" + "alnum:]{}{,111}[:digit:]", + 1, 0 }, + { "[^(\?:]MMMMMMMMMMMMMMMMMMMMMMMMMMM)cK[" + "KKKKKKKKKKKKKKKKKKKKKKKK]P{146}", + 0, 0 }, + { "([^[^wqesa)n\?L(\?<=FH+G[^rCGmfD]w)m1D\"%}]])", 1, 0 }, + { "[((\?:[^.HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH|S)xd)*[:space:](])[" + ":xdigit:]ngr'G#/B]-----------------------------", + 0, 0 }, + { ")[:lowerprint(\?<=(:]l))G p", 0, 0 }, + { "[^[^(\?<(\?<(=(\?imsximx:![(((\?", + -1, 0 }, + { "Nvvv[vv.][:alnu[^m:]+|Crrrrrrrrrrrrrrrrrrrrr[:xdigit:]j1n)v#" + "]", + 0, 0 }, + { "[^#}[(\?>:alnum:]).QQQQ[^QQQQQQ!!![!!!!!!!-s.n]se]{-238,}Tf]" + "p4721", + 0, 0 }, + { "([((\?#\?<=)+)Hr:-H]z[:graph:].{}oooooo(ooooooooo][:punct:]" + "k}}}}}}}(}}}}}\?310[|))xA5r][[^" + ":ascii:]^{,-156}{])CCCCCCCCCCC-145]FzwOD_u\?", + 1, 0 }, + { "[^[^[]{-163}{(-203}[(\?!:upperword:]PPGjZ[:xdi(\?=git(\?#:]{" + "-73}s)qqqq(qqqqqqqqqqqqqqqqqq{173,210}[:xdigit:(\?<(\?>=]WW[" + "^WWWWWWW\?*O)))Q){}08)[(\?(\?<=#:blankcntrl:]{90,}]U)])L)" + "ooooooooooooooooooooooooooox--^c[:ascii:]])s)", + 2, 0 }, + { "[(\?!:punc(\?imximx:t[^:]4F<}!)]'M-)tKKKa4904", 0, 0 }, + { "[^^{}\\(\?)" + "T000000000(\?(000)00000))+])", + 0, 0 }, + { "L[:p(\?#unct:])", 0, 0 }, + { "[:upperw(\?<[^U/)]]{}X3333333333(3333333f*])", 1, 0 }, + { "<<<<<<<<<<<<<<<[^<<<<<<<<<.][(\?#:ascii:])[:xdigit:]|^", 0, + 0 }, + { "([:punct:]{}){-167,}{-59,}Pd\"", 1, 0 }, + { "[((\?#{,214})t$)VVV[:xdigit:]{104(\?<=}D][:graph:])|H){1,}{-" + "176,}", + 0, 0 }, + { "[[([[^N,,,,,(\?=,,(\?#(\?:,,,,,,,,,,,[^,,,,,,,,,,]<,~4::_.A]" + "){-52,}-[:alnum:]Pnnnnnnnnnnnnnnnnnn)d", + 0, 0 }, + { "{-18(3,})uT{4,}", 1, 0 }, + { "[^[^[(p+c(\?" + ":])[])][:s[^pace:]][:alnum:][:alpha:]]kw06E", + 0, 0 }, + { "[^^^^^^JJJJJJJJ(JJ(\?=JJ(.6[:space:]H]{231,}A^eqqq)[:ascii:(" + "\?>(])[(\?>:spa(\?:ce:]xxxxxxxxx)@_t-))" + "138GNNNNNNNNNNNNNNNNNNNNNNNNNN[:digit:]no!`#E\?&[:" + "lowerprint:].)[:graph:]{86,}[:digit:][:alnum:]", + 0, 0 }, + { "[:g(\?<=raph:]a{114,146}(){}0Y[:bl(ankcntrl:])D)\?", 1, 0 }, + { "[^[^]*H{-192,96}S|]G)6B-kLB", 0, 0 }, + { "[[^[^][/" + "NS8`um(\?{82&{((\?{\?DW>9tN%{113}{unE", + 0, 0 }, + { "[:(\?(alpha:]`))Y2sCqWQ104", 0, 0 }, + { "(([^()Wcccccccc(\?{cccccccccccccccccc(\?)FZ{}{}`|||||||||||||*````````````````````````````'=" + "dLQmx/" + "Y.A7j'o}jn{}:})][:punct:]$|,-)!&Y:Ys#" + "ykL7JJJJJJJJJJJJJJJJJJJJJJJJJ8yex>#mv[:punct:](x@)$[:uppe(" + "\?9))i})]a!" + "lBW3p{A=or)ShE%[:punct:]{}]5r", + 0, 0 }, + { "[:pu[nc[^t:]]]}}}}}}}[}}}}}}}(\?#}])@@@@@@@@@@@@@@@@@@" + "DDDDDDDDDDDDDDDDDDD\?]xA2\?", + 0, 0 }, + { "(.[:alpha:]xB7[:alnu(\?{m:]})RRRRRRRRRRRRRRRRRRRRRRRRRRRL)[:" + "space:]G\?", + 1, 0 }, + { "[:blan(\?cii:])[:alnum:]$$$$$[:space:]3$$$$$$" + "$$$$$$$$$$$$$$$$$$$$$$$$$1", + 0, 0 }, + { "[[$zQ================(\?=========(\?====D[^))|i{}" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?)][:s(pace:]])" + ")]", + 0, 0 }, + { "[^{,-[15(\?#6}]Vwjjjjjjjj[jjjjjjjjjjjjjjjjjjS9999)]q]" + "rWWWWWWWWWWWWWWWW[:punct:]@@@@@@@@@@@@@@@@@@@@@@@@gO[:" + "blankcntrl:]>L[:ascii:]:::::::::::::::::::" + "x11uuuuuuuuuuuuuuuuuuuuuuuuuuuuu{-124,114}[:graph:]C#{tcg[:" + "xdigit:]gZZZZ[:lowerprint:]nA(_{{{{{{{{{{{{{{{{{{{{SS)\\D[:" + "alpha:]", + 1, 0 }, + { "[^(\?())]!T\?[:asc[^ii:]E:4},,]I[^b(\?:n4(njj~+{\?'k{7}{189," + "-194}{ig.[[[[[[(\?#[[[_bs6,JD`1(\?>>>>>>>>>>>>>>>>>>>>" + ">>>>>>>[^>>>(\?(>)){,-165}]", + 0, 0 }, + { "([^[][^n(\?{[[p]#})|][^]L|66666666666[:graph:]][:graph:]2[:" + "xdigit:][:space:]9b})[:digit(\?imsximsx::]+PZ):{}|E)[:" + "xdigit[^:]|>]^[:alpha:]::::::::[:ascii:]````[:ascii:]:", + 1, 0 }, + { "[:lowerprint(\?t|LQT(|)L[(:ascii:])", + 0, 0 }, + { "[^[^([:graph:](QpPdyDQ`[:alpha:](.X[:digit:]wwwwwwwwwwwwww(" + "\?imxims:wwwwwwwe(\?)*d2K0DNX5)T(].)[:digit:].", 0, 0 }, + { "([:punct:(\?#])})JJJJJJJJ[:xdigit:]" + "PPUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU.......................0hSk{" + ",89}[:xdigit:].[:xdigit:]Z", + 1, 0 }, + { "(LGTTTTTTTTTTTTTTTTTTTTTTTTTT[:alpha:]){-106,113}[:punct:]d|" + "[:digit:]kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\?wP", + 1, 0 }, + { "([^[^Sow", + 0, 0 }, + { "{-179}^[:alpha:(\?!].a'5wacA3\\\\\\\\AAAAAAAA)~^]wC", 0, 0 }, + { ">[:digit:]{,-212}+(`)LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL[:ascii:" + "][:digit:][:space:]", + 1, 0 }, + { "[[^[[^RBW{,255(}(\?(\?>=(W)_]uu][:blankcntrl:])O)]]", 0, 0 }, + { "(C_______________________________)2", 1, 0 }, + { "([/ntf_a3].)", 1, 0 }, + { "[:space:]+[(:upperword:],c7[:asci(\?<=i:]ggggggggggg)[:" + "ascii:]/1$$$$$$$$$$$$$$$$$$$$$$$$$$)", + 0, 0 }, + { "Xq{109}~EEEEEEEE[:upper[^word:]lgB:X(h[:alpha:]B[:space:]].)" + "IkaH@3}}H'yK~\?[:upperw(\?#ord:(\?:]){=================[:" + "blankcntrl:])", + 1, 0 }, + { "(([[^]]$3Xr^$%%%%%%%%%%%%%%%%%%%%%================U[:ascii:]" + ")X).FFFFFFFFFFgO[:punct:]oooooooooooooooooooBC[:blankcntrl:]" + "mmmmmmmmmmmmmmmmmmmm[:lowerprint:]rBM~rERRRRRRR[^RRRRR(\?>RRRRR])[(\?=^)X]{207,}U])))Z[:" + "blankcntrl:]]yyyyyyyyyyyyyyyy\?", + 1, 0 }, + { "[Q(\?{*[^(\?(\?!!])[:graph:]]})[:alnum:]iE)dGGGGGGG[^" + "GGGGGGGGGG[:xdigit:]w]", + 0, 0 }, + { "[^Z(\?!6(\?(\?><=)[:graph:])]BBBBBBBBBBBBBBBB^)", 0, 0 }, + { "[[^([^[^][[[[[[[(\?({[[(\?(\?imsxmsx(\?imsi[ms:::[[[[[[[[[})" + ")]$)){12,})|:::::::::::::::::::[:lowerprint:]{}{-96,-147}){" + "13,}`[:digit:]]\"^Ca%%%%%%%%%%%%%%%%%%%%%%%%%%" + "UUUUUUUUUUUUUUUUUU]]9", + 0, 0 }, + { "[^(\?(\?(\?#!<=))JLBS\"zi)'''''''''''['''''''''''''" + "piiiiiiiiiiiii(\?<=iiii]])ZZZZZZZZZZZZZZZZZZ[:space:]", + 0, 0 }, + { "({})[:punct:]", 1, 0 }, + { "E9[:blankc(\?{ntrl:]})N", 0, 0 }, + { "[:alph(\?#a:]){198,}sq\?X0B7", 0, 0 }, + { "[^\\\\\\\\(\\\\\\[\\\\\\\\\\\\[(\?<(\?isximsx:={11(\?(9,}" + "\?0])]]))\?FN3M\?{-128,}Z444444)444fbLiVN8)", + 0, 0 }, + { "[[^[^([[[[[[[[[(\?>[[[[[[[[[[[[[[[[[[[[[{53(\?<=,-175(\?>}" + "ggggggggggggggggg%))[:alnum:])[:punct:]" + "kkkkkkkkkkkkkkkkkkkkkkkkk)+" + "Soooooooooooooooooooooooooooooooo](WR+--)x36+llllllllllll{," + "35}]Fqb^=F]KKKKKKaaaaa{,131}", + 1, 0 }, + { "(g\"Ssqw<&{Cl{82,}Mdf|9cIlmCW{}[:digit:]4C{}[:alnum:]PP)", 1, + 0 }, + { "OOOOOOOU[*evVIIIIIIIIIIIIIIIII(\?#(\?#IIII)]PP[:xdigit:]" + "2222222222222222[:xdigit:]Kx)p[:digit:]", + 0, 0 }, + { "([[{248,16(\?=5(\?#}][:alpha:])|[:p(\?!unct:(\?(]", 1, 0 }, + { "[pP((\?=S)(\?#)]$[:aln(\?(um:)]2\?)$GGGGGGGGGGGGGGGGG({-U:c)" + "{-61,}[:ascii:]{-202}G", + 1, 0 }, + { "()$D[:alnum:]", 1, 0 }, + { "[(\?#^]){}[:ascii:]", 0, 0 }, + { "[uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu]FFFFFFFFFFFFFFFFFFFFFF&2e\?)" + "%oP'mc@z2b}n{xisx:)UHpP*n{}]{}fx14<7OEpE>n2150)" + "8888888888888888]^GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGS", + 0, 0 }, + { "(d)+", 1, 0 }, + { "[^.(\?(>)(\?=e)])al[:space:]x", 0, 0 }, + { "[^256c(\?!]){-19,}", 0, 0 }, + { "Q)", 0, 0 }, + { "[^s\?\?(\?{\?\?\?(\?#\?(\?cii:])){-107,-139}6/" + "{^[:upperw(\?imsxmsx:ord:]{,-47} " + "]wuH#nAn)GGGGGGGGGGGGGGGGGr[)]T{91}lJ))[:lowerprint:][:" + "xdigit:][:lowerprint:])]*", + 1, 0 }, + { "()[:space:]~!$[:alnum:]JJJJ[:ascii:]", 1, 0 }, + { "[^(\?<=)-]()k", 1, 0 }, + { "(()W){,8}ea", 2, 0 }, + { "({,-56}5G&&&&rrrrrrrrrrrrrrrrrrrrrrrrrrk.8) hWJ,TM)0Yd-", 1, + 0 }, + { "(Z-fddddddddddddddddddddddd)-{9}", 1, 0 }, + { "[^<[(\?!:asc(\?:i(\?2!+[:punct:(\?qQ[^]e[:ascii:]PP()[:digit:]NQ8%6d=&2I{-62,-142}w]].e{" + "}*", + 1, 0 }, + { "{,-219}xxxtEEEEEEEEEEEEEEEE[:pun(\?(ct:])qqq)" + "nnnnnnnnnnnnnnnnnnnnnnnnnnn", + 0, 0 }, + { "[:di(\?>git:])W4", 0, 0 }, + { "([^y])Fkvto$", 1, 0 }, + { "[^($$$$$$(\?!$$$$$(\?{$$$$$$(\?<=$$$$$$$$$$$+===)[:alnum:]" + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM)Z]{}^[:blankcntrl:]--" + "xxxxxxxxxxxxxxx[^xxxxxxx)\?tVG\?{232,81}{121,}xn{,-226}})" + "tttttttttttttttttttttttmu(\?[:digit:]S[:space:]t", + 0, 0 }, + { "()n", 1, 0 }, + { "[:upp(erword:]$)<}.vZM)rCD&{5(\?msxisx:7,}qqqqqqqqqqqqqqqqqq{31,}@w#W:(@(" + "\?:zp$YYYYA[:alpha:]{1}A)*dZJ\"5OG|\?(\?#a])]|){-150}[:" + "xdigit:]", + 0, 0 }, + { "[($)gwo{`\"]{-160,}" + "\\\\\\\\\\\\\\\\\\\\\\\\\\66666666666666888888888888", + -1, 1 }, + { "((}DA+Rc000000000000000000)%vvvvvvvvvvvvvvvvvvvvv%C&emZ*[:" + "alnum:]#m/" + "D[:graph:][:blank[^cntrl:]E{,168})" + "kkkkkkkkkk000000000000000]", + 2, 0 }, + { "[^[u*(\?#x01234)oxGGGGG(\?([GGGG)GGGGGGGGG]^U)!!CCCCBM`4QB^" + "XEN]{,-60}[:upperword:]G]", + 0, 0 }, + { "(%)~t{S,K^MI3PMo)=b", 1, 0 }, + { "[[[^]{}eU([:xdigit:]&&&&&&&&&&&&&&&&&)\"W|43[:alpha:][:" + "graph:]J8b[:blankcntrl:]gggggQ{,183}{,-254}\?[:ascii(:]{," + "134}", + 1, 0 }, + { "[[([^[^([^(\?=)1RRRRRRRRRRRRRRRRRRRRRR(\?:(\?(\?(\?!=#RRRRR(" + "\?=RRRR(\?<[^!Ru)])]o[:[graph:[^]{,7})[:digit(\?::]{-215,}e[" + ":space:]]", + 0, 0 }, + { "({{{{{{{{{{{{{{{{{{KKKKKKKKKKKKKKKKKKKKKKKKKKKKBBBBBBBBBBBB)" + "[:space:]0[:alnum:]HcctQA", + 1, 0 }, + { "[^(pP7(HsN[^g{186,-87}\?\?]EQ%u:-Y)+>>>>>>>>>>>>>>>>>>>>>pP]" + "[:alpha:]", + 0, 0 }, + { "[(.{141}h|)((\?:\?=@Q} " + "ghcC{+*(R)D+][:lo(\?#werprint:]" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz))", + 0, 0 }, + { "[^({}S)PPFl(])-216", 0, 0 }, + { "[([[^(((([(\?#^[^[^\?4[(:[dig[^it(\?(:]{122,})y\?", 0, 0 }, + { "[[2${188}u{1(4(\?(1,1(\?{98}e{&tbaoI]q)[:punct:])d}))" + "Nqffffffffffffffffffffffffffff[:ascii:]+]", + 0, 0 }, + { "()K-", 1, 0 }, + { "[[{2(2((\?(\?!()2})])[:alpha:]fVVVVVVVVV{-47}):::::::::::)" + "\?vwyyyyyyyyyyyyyyyyyyyyyyyyy-]{}", + 0, 0 }, + { "ivcs)g", 0, 0 }, + { "(hhhh[^hhhh(\?{h\?]})%%%%%%%%%%%%%%%)\"+38mbY:s9{/d# " + "zaNnbQb)b:*zpKI{-26,-189}", + 1, 0 }, + { "S*(#)[:graph:]lllllllll&G)t", 1, 0 }, + { "([^[(([\?=\?\?%)$Lwq[:alpha:]{-115,}=============" + "==================={127,}", + 1, 0 }, + { "e)", 0, 0 }, + { "[{,2[5}Klen+D0'YX(\?<=|_H]I,Y\"*/<3sM[:digit:]])#.", 0, 0 }, + { "[:(xdigit:]){[:digit(\?mxmsx::][:as(\?<=cii:]d!{135})#)pP[:" + "space:]Syyyyyyyyyyyyyyyyyyyy\"Gg8", + 0, 0 }, + { "[(\?()])", 0, 0 }, + { "[^([^[^[[^[:alpha:]SIus[^f][^((\?n*)P<" + "3tttttttttttttttttttttttttt)n{}[:graph:]" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{,83}[:digit:])" + "0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[:alpha:]{-155,}{151,}", + 0, 0 }, + { "Ue{,254}+f[:lowerp(\?<=rint:]U.fff)", 0, 0 }, + { "QQQQQQQQQQQQQQQQQQQQQQQQAY===========[^=S|[^[" + ":alpha:]G/]qqqqqqqqq{}[:xdigit:])..k", + 0, 0 }, + { "[([^[[:space:]ffffff(\?=ff]M]))[:xdigit:]UbCI,CzalLU*y5I[:" + "digit:]r{-30,180}{-209,-45}Paf]", + 0, 0 }, + { "[^[h(\?{hhhhhhhhhhhhhhhhhhhhh})]{,143}[:lowerprint:][:ascii:" + "((\?(\?=])[:asc)ii:])zp]", + 0, 0 }, + { "[[(\?{]})]", 0, 0 }, + { "[[1\"3m^,(\?2m[M/" + "2222222222222222222222222222(\?:22222222222(\?#22(\?:(\?=" + "22222{,243}]x68+I/" + "K)11111111111]\\pP[:graph:]$[:space:]^{}A)[:xdigit:]-={>", + 0, 0 }, + { "[(\?>[(^()Vty2vvvvvvvvvvvvvvvvz^])ZZZZZZZZZZZZZZZZZZZ-------" + "---------5\\dVLSp8UE2m+z3X/Sd", + 0, 0 }, + { "[}}}}}}}}}}}}}}}}}}}(\?#}}(\?<=)|*C " + "]*29JW7O9mEB]pE_OoxN)[:alpha:]", + 0, 0 }, + { "([^((\?<=\?)D{,200}.[(\?#:ascii:])[:space:].)[:alpha:]D|[:" + "graph:]{,-41}*LLUUUUUUUUUUUUU{-189,-131}]qHR])]][:" + "blankcntrl:]M[:alpha:]x9[:upperword:]|[:xdigit:]b", + 1, 0 }, + { "()[:digit:][^[U}-]]{,206}V*WJ@R]\?", 1, 0 }, + { "[^](\?#{}(\?[<=)yv)]r", 0, 0 }, + { "({,-192}//////////////////////7!eW_0eoL){}", 1, 0 }, + { "^[:punct:(]+)IIIIIIIII[:punct:]P$pP", 0, 0 }, + { "[(\?=|U)^-]{-52,-72}[:digit:]*6666666666\?{{{", 0, 0 }, + { "([^f(\?:+{1((\?=34,}]))^)s0bux7\?5`Bwr[:upperword:])Dy+", 1, + 0 }, + { "AL{}:::::::::::::::::::::::::::::::{,(104}~@,Ysey@h).", 1, + 0 }, + { "[^((.)))(\?()))))))))))))))))))))(\?msxims:))))))))))[)][:" + "upperword:][:alpha:])", + 0, 0 }, + { "[^(()f])G^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^T{}N*nK[G]{,61}^^^^^" + "^^^]", + 0, 0 }, + { "[(N::(\?<=[:digit:][:graph:][:space:]xB5[(:xdigit:]|Yv{}" + "HHHHHHHHHHHHHHHHHHHHHHHHd).[:g(\?<=raph:])[:digit:]<<)[:" + "digit:])[:space:]Q[:punct:]x7C]", + 0, 0 }, + { "[^((\?(\?(())a)(\?!){})W)pP3333333333(" + "33333333333333333333hhh]{})", + 0, 0 }, + { "[^ [ " + "a*FFFFF[^FFFFFFFFFFF(\?<[^!FFFF(\?=FF])])L1]{,-52}{B-bxsPKg{" + ",8}[:digit:][:punct:][:upperword:]DD${,-131}", + 0, 0 }, + { "($$$$$$$$$$$$$$$$$$$$$$$$$$$$$^pP),,,,,,,,,,,,,(,,,,,,,,,,,," + ")QQQQQQQQQQQQQQQQQQQQQQQQ", + 2, 0 }, + { "[:lowerprint:]|l{(,-54}C{}*-)IIIIIIIIIIIIIIIII", 1, 0 }, + { "()+", 1, 0 }, + { "[(([(\?{[:punct:]]|))[[[[[[[[[[})]WWWWWWWW&$$$$$$$[:graph:]", + 0, 0 }, + { "[^(\?{}){(107[(^,}][:space:[]))^w,&aPPPPPP[^PPPPP{117,-213}" + "s\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?]]]222222[:d(\?(" + "igit:]NNNNNN)NNNNNNNNNNNNN8)I", + 0, 0 }, + { "[^(\?9C^:\?X_KK]2sw@hHZT!],uuuuuuut|lFW()''''''''''''''''''" + "'''[:graph:]<~v{-251}0[:digit:]C[{222,}]{,41}{}*g^UuS/" + "{-114}", + 1, 0 }, + { "(D{,-79}[:gra(ph:(\?(]C[:ascii:]))I[tC.%tkllll[^" + "llllllllllllllll]&&&&&&)&&&&&&&&&&&&&&&&&&&&&&)]10435", + 1, 0 }, + { "[:al(\?{[^num:]]})}x'[:(\?#xdigit:])" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKKKKKKKKKKKKKKKKKKKKKKKKKKKKTT" + "Tr*%{~f", + 0, 0 }, + { "[ZQKEEEEEEEEEEEEEEEEE(\?[:alnum:]W[:space:]]D)|L", 0, 0 }, + { "(M(MM)[:alnum:]|[:lowerprint:]4)", 2, 0 }, + { "[[^(\?:{}{2[2(\?>0,})]]]Etu)-)", 0, 0 }, + { "([^[^^z[:graph:]]#{-144,96}[:punct:]!4LY//////////////////" + "SSSSSSSSSSSSSSSSSSSSSSSSS[[^:xdigit:]\?`-!L#p0{52}]%{-121,}[" + ":graph:]]WqJ>$6UBg{,7}[:blankcntrl:])[:upperword:]y2wW!A[:" + "blankcntrl:]0CN\?", + 1, 0 }, + { "[[^(\?:|+bII(IIIIIII(\?(\?>!)275SIIIIIIIIII(IIIIIII(\?=" + "IIIIII[:graph:]|)`]S\?.}A)[:alnum:]Jgggggggggg{-150,}{-89,})" + "[:alpha:]Q)|07be5:j)]", + 0, 0 }, + { "([(\?i(ms(\?=x-x(\?>:))C)]){})>eIqm~lFb[:upperword:][:" + "blankcntrl:]w=[:digit:][:graph:]", + 1, 0 }, + { "([HHHHHHHHHHHHHHHHHHHHHHHHHH[^HHH(" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?!!!!!!!!!!!!!!!!!!" + "!!{23}]~J=[:ascii:]tttttttttttttttt])-216", + 1, 0 }, + { "B{[^-32,246}{13(\?!0}q>GVQw*[:digit:][:punct:]." + "77777777777777777777`T(-t01odD]\?${}{-247}+gV{131})+[:" + "lowerprint:]m/z~d", + 0, 0 }, + { "[t[$FV+(\?=E=[^])]-$U{-22[5,}{253,}08g]$[{}][:xdigit:][:" + "punct:]{-18}{-173,}]{,-191}V_|90", + 0, 0 }, + { "()$", 1, 0 }, + { "[^[^((((((((((((((W[(\?::blankcntrl:]&-JH]J){93}LLLLLLL|r{," + "221}tY/172]-AS", + 0, 0 }, + { "[^()(\?{qqqq(\?msimsx:qqqqqqqqqq3999999999999GGGGG|S*W%{," + "128}][:xdigit:]AJt]}\"Zf!lRpr{>){,36}})", + 0, 0 }, + { "[([]^]^)", 0, 0 }, + { "([.(\?#){}[:alpha:]\?S{2}P%Gw]" + "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnYiq5)>i*r<", + 1, 0 }, + { "[ggggggggggg$PPP:S " + "(:]N{239,}|A[:lowerprint:]vvvvvvvvvv[:lower(print:]{-184}({-" + "133,}+)[:punct:]P/Q.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + 1, 0 }, + { "(RRRRRRR[^RRRRR[RRRRRRRRR])]", 1, 0 }, + { "[(\?:^])D%", 0, 0 }, + { "()[]#C[+[j]{,29}-]", 1, 0 }, + { "(([(\?(((\?{\?!(\?=\?=#[Es*){02$r'}(\?:3pz)" + "uPPPPPPPPPPPPPPPP(\?(\?>:PPPP][:graph:][:ascii:]`.)[:punct:]" + "[:a(\?mxi:lnum:])r)$)[:xdigit:]$[:(\?=digit:])aa[^]a)\?])" + "sQQQQQQQQQQQQQQQQQQQQQQQQQQ^|$)-}))", + 2, 0 }, + { "z@@@@@@@y${}[:(\?:upperword:]l\?{,144}-)", 0, 0 }, + { "[:aln(\?:(\?>um:(\?imximsx:]){})FGGGGGGGGGG|-p){,105}", 0, + 0 }, + { "[[{17}llllllllllllllll(\?:lllllllll{,(\?#-94}OUUUUUUU(\?#" + "UUUUUUUUUUUUUAA]p[:digit:]{-1(57,}5yyyyyyyyyyyyyyyyyyyyy[:" + "alnum:]v{-185}^^^^^^^^^^^^^)d[[[p)]))", + 1, 0 }, + { "()|[:digit:].E2o", 1, 0 }, + { "()3[:lowerprint:]", 1, 0 }, + { "[(\?{(\?#(\?>SN}[^)z+r^t[:digit:]seP[:alnum:]$b1ZY[U(\?{}000000000000000000000000000000$|)", + 0, 0 }, + { "[:(\?=digit:])v{164}", 0, 0 }, + { "[:graph:]h[:upper(\?(wo(\?{rd:)])00000[^000000000000})." + "4OEVf{,-46}]A", + 0, 0 }, + { "[](((((((((((((((N{{{{{{{{{{{{{{{{,-1}e]a{-166,-44}", 0, 0 }, + { "([[^[^[(^[]]YYYYYYYYYYY]D.cQ{}[:alpha:]ttttttt000000[^0000(" + "\?raph:])[:punct:][:upperword:]LV\"t+t!)[:" + "ascii:][:lowerprint:]q", + 2, 0 }, + { "[[[^([7(\?[R]]$PeFuufcBA`qr!!!!!!!!!!!!!!!!!!!!!!!!!", + 0, 0 }, + { "[[(\?#F^(\?wwwww)3z/57z){34}]/(/////////////[^////" + "//////////////)]E%)L{-133}]*$]", + 1, 0 }, + { "(!)GS[:ascii:][:punct:]{235}T'&-_h\"", 1, 0 }, + { "(){}", 1, 0 }, + { "[[^((\?!(\?<=)*QF[:alpha:])([^[^\?qqqqqqqqqqqqqqqqqqqqqqqP6W0_'O)" + "Bur*'6&*t)]{65})+", + 0, 0 }, + { "([(\?=)]wr$7f5ru){100,}[:xdigit:]y{}[:digit:]{}2n@P|9#mru~" + "97{-189,73}$a", + 1, 0 }, + { "({-113,213}){-172,221}B[:ascii:]{,-48}", 1, 0 }, + { "[^[[Xf`````((\?{(\?<=\?imsmsx:`````````(\?!`````````[```(" + "\?mximsx:``(\?(&|o{xIaO][:)space:]3))\?])+)*<|@@@@@@@@@@@@@@" + "@@@@@@@@){-251,}{}]*[:graph:]1!azE\?|-120u*][:lowerprint:]}" + ")", + 0, 0 }, + { "[[[^##(\?################(\?>(\?(##t)][:punct:])b))<<<<<<<<<" + "<<<<<<<<<<<<<<<<<[:alnum:]y " + ">u=l:rp8i3Ci#]46%NIO-W[:space:]IIIIIIIIIIIIIIIIII]W[:space:]" + "f]l{-253}", + 0, 0 }, + { "[:graph:]L{-136,175}{[^}h(\?=t)Q]ooooooooo(" + "ooooooooooooooooo_)[:space:]q\?", + 1, 0 }, + { "()$.", 1, 0 }, + { "[(\?\"y8].]::::::::::::::" + ":)pP5-]p)O{,199}xxxxxxxxxxxxxxxxxxxxxx[:ascii:]%", + 1, 0 }, + { "([:alpha:]Fs)Z", 1, 0 }, + { "[()]{209}[:alpha:]hhhhhhhhh(hhhhhhhhhhhhhhhhhhhhh)pP<<<<<<<<" + "<<<<<<<<<<<<<<<<<<<<<", + 1, 0 }, + { "-{-8,}.[:(\?imsxx:ascii(\?D9'", + 0, 0 }, + { "[#(\?msximsx:#########################-IIIIIIIIIIIIII(IIII(" + "\?#IIIII((\?#[^III{})N.[(\?=:lowerprint:]))CwT,,,,,,,,,,,,,," + ",,,,,,Sq]$CCCCCCCCCCCCCCCCCCCCCCCuuuuuuuu])))", + 0, 0 }, + { "[:xdigit:][(\?#]){13}{,75}lllllllll", 0, 0 }, + { "[c]QQQQQQQQ1+{-252[(\?#}33333])[:upperword:]", 0, 0 }, + { "P@i #>>PF!@8G<[(\?:^P]-)D", 0, 0 }, + { "uZZZZZZZZZZZZZZ[^ZZZZZl*-211{199}(\?!p])" + "EEEEEEEEEEEEEEEEEEEEEEEEEEED[:lowerp(\?msximsx:rint:])", + 0, 0 }, + { "[(\?!^])021[:graph:]'", 0, 0 }, + { "\\(\?>[(\?<=:ascii:]{}[:alpha:]d8}G))", 0, 0 }, + { "[^[((\?!1)[^,a|]\?{,242}[:alnum:])X\"a", 0, 0 }, + { "pP[((\?simx::a(\?!lnum:]vvvvvvvvvvvvvvvvvvvvvvvvv)|O0)[:" + "digit:]ooooooooooooooooooooo)" + "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"", + 0, 0 }, + { "_ L:8J-~ Y$[:uppe(rword:]{,-184}]{}6.A)", 0, 0 }, + { "{,105}.(9]]{-12})N@0nOOE", 1, 0 }, + { "HHHHHHHHHH[:xdigit:]uuuuuuuuuuuu{}E^X\\\\\\12601", -1, 1 }, + { "( o)=\"OU7h{V>", 1, 0 }, + { "[[:xdigit:])))))$[:xdigit:]+{152}{,-50}(c),,,,,,!!!!!!!!!!!!" + "!!(\?>!!!!!!!!!!!!!.[:digit:]i>\"O'i9])-175d_", + 0, 0 }, + { "[([^[^[^([[Eeee[^eeeeeee(\?(\?(\?!(\?>a:]a{,166})/////////////////////" + "[:gr[^aph:])Gpu", + 0, 0 }, + { "(7)NNNNNNNNNNN132", 1, 0 }, + { "[([\?#^[]{QKm$v])][:alp[^ha:]]", 0, 0 }, + { "(:{86})7{K|[:alpha:]{O", 1, 0 }, + { "([Y(\?{[[^:alnum:][:alnum:][:digit:][:a(\?(lpha(\?(:].})", 1, + 0 }, + { "[[({29,-30}([[^:digit:])Y]]J=~{,220}[:blankcntrl:])" + "0ooooooooooooooooooooooooooooooo[:punct:]&]", + 0, 0 }, + { "[^1Dx32[:alnum:]]{[(\?::punct:]MMMMMMMMMM)12759", 0, 0 }, + { "([[[]]*|(_])[:u(\?{pperword:]})", 2, 0 }, + { "[:upper(\?(wo)rd:]){-16,250}", 0, 0 }, + { "([^{194}i(\?({161)}PP\\S{}{,-14}]))z{208,225}BpPEt", 1, 0 }, + { "[(\?m-ms:)}&!@29k0sUqzt9}<-x|A$!+G>>>>>>>>>>>>>>>>>>>>>>>>>>" + ">>>>>>CCCCCCCCCC-][[:space:]][:space:]El", + 0, 0 }, + { "()[:digit:(\?isx(\?>ix:]K^WQQQQQQQQQQQQQQs)[:lowerprint:])", + 1, 0 }, + { "[a|(\?imix:S(\?(SSSS)SS(\?>S)]W)8t[:ascii:]f$)[:alnum:]" + "111111111111111111111[^[:space:]x{12729}+'''''''''''''''']", + 0, 0 }, + { "[^(\?!(\?(\?#=)a)[:punct:]=2)(){}$$$$$$$$$(\?ims(\?#-isx:$$$" + "$$$$$$$$$$$$$(\?#$$s)x{294b}##############################" + "slllll)]){,209}333333333333333333G:v2/K", + 0, 0 }, + { "[^]ub(\?<=)vQ6(\?#Z\"3.)[:space:]u[[:digit:]]" + "7777777777777777U'{}sssssssssss", + 0, 0 }, + { "(([(])`[:ascii:]b)", 2, 0 }, + { "[[[^[^([^[^(\?=(\?imxisx:[[^w])", 0, 0 }, + { "pppp(pppppppppp-{-175}Nb>k&)sssss{-190,-54}", 1, 0 }, + { "()OJ@`'%[:(as(\?!cii(\?#:]))+pffffffffffffffffffffffffffff{," + "162}[:ascii:]5)s-[:graph:]", + 1, 0 }, + { "[(M{}Ux5{jaW/" + "{}[^u[:alpha:]s^{84,}PPb@Wt$(\?>nha:al[^pha:]])\"O\"vN", 0, 0 }, + { "[(\?>d8E@b.{(\?<=,-250}(\?=mx48[:punct:]^&)]nAeYY)W)-13272", + 0, 0 }, + { "22222222222222222222222222///////////////////" + "[:digi(\?#t:]eM)[:lowerprint:][:alpha:][:alpha:]EEEEEEEEEEE", + 0, 0 }, + { "[(\?={38,223})^\\\\\\\\\\\\\\\\L(\?:{,-50}3|)}r]aW\\x70U{-" + "110,}8LUf)w]4+oav", + 0, 0 }, + { "G[:upperword:]v[:lowerprint:]-tu)j8CK", 0, 0 }, + { "[([([^().(\?(\?><=c)'(\?<(='(\?L\?q!G))|)(\?=n(\?(^tk)T-z$q!D|2[^a:]W,[4DLR[^^8THMtVv~KKw(\?>)pPF)].{-" + "245,}]))fffffffffd[:alpha:]zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + 1, 0 }, + { "[^[[^]{-[1(\?imximx:83,}{,182}][:graph:]]^])-bTO X0P", 0, + 0 }, + { "[11111111111(\?#11111111]U[:asc([\?!ii:]{,37}+{-89}){-170," + "218}{-21,})f[:xdigit:]]P.[:xdig(\?:it:]145)YYYYYY$S@:@@@@@@@" + "@@{-150,-109}", + 0, 0 }, + { "{-40} (\?( (\?{ " + "(\?!]E{-29})pP)})ZpP", + 0, 0 }, + { "(t|{}c[^z^\?(@YLD]bSSSSSSSSSSSSSSS)+{{{{{{{{{{{{{{{[:xdigit:" + "]n>1)WkF}7", + 1, 0 }, + { "W22[0Q[^d-d{}PPPPPPPPPPPPPPP<^FZ(\?<=\"[U]Yo}9H'cYy]S[:" + "alnum:]^8wTDH)^u", + 0, 0 }, + { "([^[(\?:(\?>((\?#$)(\?{^(\?>))///////////(\?>/" + "ggggggggggggggggg{1(\?!90,-13}\\D)Dyyyyyyyyyyyy(\?!y(\?ankcntrl:]" + "))(^m+)zSiZ " + "F4[!]VV$E{-9,-100}''''('''''''''\?DEOOOOOOOOOOOO############" + "###[:space:])HHHH)[:digit:]'////////////", + 2, 0 }, + { "[^*}(\?>)(\?:7Q=#+]KKKKKKKKKKKKKKKKKKKKKKKKKKKG)]]]]]]]]]]]]" + "]]]]]]]]]]]]]][:alpha:]-{}", + 0, 0 }, + { "[n(\?<(\?#!nnnnnn55555{205,}!)[:alnum:]^]!!!!!!!!!!!!!!!!!!!" + "!!!![:punct:])[:x(\?(digit:]vr)|'n6W5 D&jk[:punct:]5)", + 0, 0 }, + { "[^P(P{(\?i(msxisx:235,}))***])[:alpha:]^", 0, 0 }, + { "[([t(\?a:])x11{-144,45}.", 0, 0 }, + { "[]{#y.^(\?{{}&&&&(\?:[^&&&&&&&&)[:punct:]n{190}OylBQ{(\?!-" + "73})2u',x(\?#Ds(\?#{})j(\?{-})})u0(((((((\?{(((([:alnum:])" + "MC})b=71TncyE>[:xdigit:]*\\f]{}]\"p#!8twZT\")[:punct:][:" + "space:]", + 0, 0 }, + { "[^(Z6]8)|'@p8{}[:upperword:]MMMMMMMMMMMMMMMMMMMMMMMMMMMM{}" + "7c", + 0, 0 }, + { "$0)@#vp,VcJ.Bdh", 0, 0 }, + { "[[^(-])nnnn+s`[:alpha:][:blankcnt[^rl:][:upperword:]{-15,}][" + ":g(raph:]c]){,-177}6[:upperword:]##################{,-14}", + 0, 0 }, + { "[[(5C{86(,}PPrrrrrrrrrrrrrrrrrrrrr{150,182})N{}LSC|)-[:" + "alnum:]{}KKKKKKKKKKKKKKKK<4=~7K3PPPPPPPPPPPPPPPPPPPPPPP[:" + "lowerprint:]]]", + -1, 0 }, + { "([^(x{145b[5}^hfc.0)+]z@_&lA{-34,}])X\?", 1, 0 }, + { "([(\?<=)(\?!])l)L", 1, 0 }, + { "({-104,}DrPPDF4444444444444[:space:])[:space:]", 1, 0 }, + { "())))", 1, 0 }, + { "[[^((\?>\?(\?[{})q5v}r7t(P)xtffffffffffff))]{,-66}kdExX&-" + "SCeCzzzzzzzzzEc)E,\"^I]x{e629}|{}]", + 0, 0 }, + { "[h[:punct:]p\\[\\\\(\?:\\\\[^\\\\)Eo#:C$u[^T/" + "ysA[*%nM:f]{,221}[:lowerprin[^t:]{]bx{f285}E]E[:alnum:]+]" + "1oe3B][:alp(ha:]]fh7}M$l)D{17}", + 0, 0 }, + { "IIIIIIII[^IIIIIIX]-_S[:digit(\?#:])" + "33333333333333333333333333[:punct:]iiiiiiiiiiiiiiiiii", + 0, 0 }, + { "[^[[:punct:](\?((\?:^ " + "#Q_po(\?=[:alpha:]{}z()(\?!======'wq$Q2)LLLLLLLLLLLLLLLe(" + "C9gggggggggggggggggg[(\?<=:alnum:]()\?(\?=a!Ib1P]])])~~~~~~~]xE9", 0, 0 }, + { "X()", 1, 0 }, + { "[^()(\?#G(\?777777])", 0, 0 }, + { "(),e<^X~{[:alpha:]{}G{70}", 1, 0 }, + { "({-211,}'){}", 1, 0 }, + { "[^(\?imsxsx:{}[*])cccccccccccccccccccccccccccccccc[x))(\?:]r.]]]))[" + ":graph(\?<=:])))", + 0, 0 }, + { "[^([(\?#)(\?(\?(<=)l|\?(\?!])kkkkkkkkkkkkkkkkkkkkkkkkkk", 0, + 0 }, + { "[:xdigit:]K(KKKKKKK)^3c.OOO{-240,-10}2{-97,-139}*{-34,}[:" + "xdigit:]", + 1, 0 }, + { "[([^66666666F(\?>FFFFFFFFFFwpP)LLLLLDeDA&Am$l[:xdigit:]!T5#]" + "n[:alpha:]U*)))))))))))))PP]", + 0, 0 }, + { "[[[:punct:]u^[:xdigit:]L(\?:[:xdigit:][[:graph:]PP{21}A[:" + "alpha:]8%I(M%bSSSSSSSSSSSSSSSSSSSSSS]]]]]]]]]]]]]]]]]]]" + "]]]]]]]]]]]{,-1}])[:blankcntrl:]============================" + "===[:punct:][:blankcntrl:]Z[:space:][:ascii:]$|$[:" + "blankcntrl:] JR.{,133}[:alpha:]$\?)<]", + -1, 0 }, + { "(OL[:u[pperword(:][:s[^pace:].[:spac(e:],,,,]*])$)\?)", 1, + 0 }, + { "(VI[:digit:][:alpha:]6)EG", 1, 0 }, + { "({}){-2,-40}rrrrrrrrrrrrrrrrrrrrrrr[:punct:]", 1, 0 }, + { "()q", 1, 0 }, + { "[^([^[([^C|])]{,-56}[:xdigit:]{-144,}V])fYv{-[40,-58}$@@@@@@" + "@@@@@@@]|Y(-]-.]h-[:dig(it:])>>>dddddddddddddddddddddddddd{" + "101,}", + 1, 0 }, + { "([P,{1(\?(\?(<=28,-218[^)}LoZX)])!!!!!!!!!!!!!!*[:blank(\?!" + "cntrl:]ed)\\\\\\\\\\\\\\\\\\\\[\\L\?][:graph:]:*Y{-108,120}" + "xCC)]", + 1, 0 }, + { "(A[:space:]PP{185}a^!!!!!!lllllll)*db\?$Pfr", 1, 0 }, + { "{-21,-118}kG[(\?{:xdigit:]})[:punct:]{69}" + "Qyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy5{}TTTTTTTTTTTTTTTTTTTTT", + 0, 0 }, + { "[[^[P(\?<=P$X>0^d.[:punct:](\?#ccccccccccccccccccccccccc{}" + "3N000(\?>00000000000000000000000000000]f[:punct:]5)).R======" + "=========={,222}^wwwwwwww$)]-{} " + "]{,-22}CjP{242,}", + 0, 0 }, + { "[(\?#^]{})", 0, 0 }, + { "[^([[([([[([^[^(\?:(\?(\?(!)]\"))h>\"RRRRRRRRRRRRRRRR[^" + "RRRRR{68,-65}7Q(\?{]", + 0, 0 }, + { "(P{}){175,}PP{}rttttttttttt", 1, 0 }, + { "[:bla(\?{nkcntrl(\?#:]})))))))))))))))))))))))!!!!sR{})", 0, + 0 }, + { " [:digit:]dAAAAAAAAAAAAA^[:ascii(:]55)^", 0, 0 }, + { "($*)dZY", -1, 0 }, + { "[:graph:][:lowerprint:]S[:gr(\?=aph:]{-128,}" + "666666666666666666666{}[:upperword:]|" + "nnnnnnnnnnnnnnnnnnnnnnnnnnB)c[:xdigit:]{-225,}{-4,}{-192,}" + "QQQQQQQQQQQQQQQ@@@@@@@@@@@@@@@@@@@@@@.", + 0, 0 }, + { "([:digit:]s{44,}{}{-31,}c{,-130}pP){-241,}UeN", 1, 0 }, + { "([^)((\?>\?#{}hK\"V2\?d][KKK(\?imsxim:KKKKKKKKKKKKKKKKKKKK[^" + "KKKKKKKKKWWWW[WWWWWWWWWWWWWWWWW)B])_l_3", + 1, 0 }, + { "[(^[(\?!*){[^,91}].j]*]L)*c|[:alpha:]&", 0, 0 }, + { "[^[[[^[777GGG(\?:W_U(\?imsxms:[:punct:]A]-)[:digit:][:" + "blankcntrl(\?(:]][:alnum:)])]WRRRRRRRRRRRRRRRRRRRRRRRRRRR]{" + "31,}[:xdigit:]][:xdigit:]))))))))))))))))))))))$[:xdigit:]", + 0, 0 }, + { "[:ascii:]m*[:punct:]#[(\?>>>>>>>>" + ">>>>{,-129}))\?{-226,}^P)R", + 2, 0 }, + { "[^[[nnnnnnnnnn(\?=nnnn(\?!nnnnnnnnnnnn(\?#nnnnnn{,-38}N){" + "202,}]$[:alnum:])]t][:alnum:[]^=w){237}][:alpha:]-[:alpha:]+" + "e", + 0, 0 }, + { "()[(\?(:digit):]+qc)O88888888{,151}aJ", 1, 0 }, + { "([^([(\?!sv(\?=)d]{-200,})N))]Z{-73,15}", 1, 0 }, + { "([\?\?\?\?|||||||||||(\?{||(\?=||||||||-}[))Ehhhhhhhhhhhhh{," + "202}&TcfL((\?:>)((\?!\?>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$8[:" + "alpha:]\\d])]C[:graph:]h*,\"\?u{|mU,a)[:blankcntrl:][:" + "lowerp(\?>rint:])PPnP+9.[:xdigit:]*PPjjjjjjjjjj~y<#*scf_\"^" + "e[:xdig(\?(i)t(:])~$y)^){-131,77}^L%", + 1, 0 }, + { "[^[(((\?>)$}h9$B5+yhU/" + "Nqh$YYYYYYYYYYYYYYYYYYYYYShK)3WHw1vMMMMMMMMMMMMM(\?=" + "MMMMMMMMMMMM[:alnum:]/" + ")dddddddddddd(dddddd\"e5zLW)+![:space:]+BHGHfAS]" + "\?IIIIIIIIIIIIIIII*&&&&&&&&&&&&&&&&&&)NNvwDteepjdm<<<<<<<<<<" + "<<<<<<<<<<<<<<<<<<<<${61,219}D][:digit:]0", + -1, 0 }, + { "[:punct:][{177,(\?=234}]ix9*)", 0, 0 }, + { "([^K{,3(\?<=4}]I)\?U)", 1, 0 }, + { "[([^[[[^([([^[^(\?=])X", 0, 0 }, + { "[:blankcntrl:(])qd_R\?{\?r[=\"[^[^6]vX8)a+{C%H84CK6Uy#E]sE{" + "208}", + 0, 0 }, + { "PPPPPPPPPPPPPPPPPPPPPPPPPPnnnnnnnnnn()[:upperword:]us", 1, + 0 }, + { "x{,46}[:graph:]LU{}CU)", 0, 0 }, + { "()-t|[^W{}][:lo[^werprint:]{}]\?b5", 1, 0 }, + { "()x5A", 1, 0 }, + { "[([^]-217)]s{-47,135}0000000000000000000000000000000{,-108}", + 0, 0 }, + { "[^((\?{[^L\?u]})f", 0, 0 }, + { "()[[^^(\?{y(\?=VF_(\?<=]D}))]-= {46,})^5bIEQ{,-96}Z", 1, 0 }, + { "([^{}f[:punct:]\"X%%%%%%%%%%%%%%%%%%%%]5{-194}A[:punct:]" + "mnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn+AAAAAAAAAA-)", + 1, 0 }, + { "(CCCCCCCCCCCCCCCCCCCC{-230}352{-182,-68}O4{})", 1, 0 }, + { "([^[^\?[:space:]$TTTTTTTTTTTTLLLLL[^LLLLLLLLLL[^({}{4,-179}]" + "]J] C]){}C{}{-224,})QQQQQQQQQQQQQQQQQ^", + 1, 0 }, + { "([[:alnum:]].){-155,-82}dzI{55,}^", 1, 0 }, + { "([[:alnum:](\?#{88,-178})[:graph:]NC\"pI[:punct:]rmWd5y^p+" + "gUP]YYYYYYYYYYYYYYYYYYYY~{,-62}{,200}{-109}{}+" + "333333333333333333333333333333{}p)^.hhhhhhhhhhhhhhh", + 1, 0 }, + { "[000000(\?mmsx:00000000000000000000000)M]]]]2*`[^]QQQQQQQQ(" + "\?<=QQQQQQQQQQQQQQQQQQQQQQQ])\"5j[bbbbbbb(\?{bb)o{}3(\?imxisx:E]g})YYYYY[:" + "blankcntr(\?#l:].(()w264[:ascii:]^)[:ascii:]G)&(n " + "{^PGn[:xdigit:])nv_e|]{-103,30}", + 3, 0 }, + { "[^(([(\?!{}@[^HCO[[^^D[|]{,-49}][:xdigit:]]c`4[:ascii(\?ggggggggggggggg\\\\\\\\\\\\\\\\\\\\\\\\\\Ef[:" + "space:]\?][:ascii:]{21,}", + 0, 0 }, + { "([:xdigit:]W[:u(pperword(\?::]jS " + "[:upperword:]*)[:alpha:]nnnnnnnnnnn))-148}SSu", + 1, 0 }, + { "([^(\?!\?)[(:upperword:])Bx^x$~lCr6*)6", 1, 0 }, + { "[{,-78}Y[:xdigit:][^s(\?>]P[:space:])]YYYYYYYYY[:punct:][:" + "alnum:][:blankcntrl:]", + 0, 0 }, + { "([MMMMMM(\?(MMM)M(\?<=MMMMMMMMMMMMMMM[^M)]en][:punct:]-[:" + "alpha:]))Nr[:space:]", + 1, 0 }, + { "~=1([^(\?=(\?:l){}])j{-44}{-18}[^u[:graph:]]{-187,}[:xdigit:" + "]w[:alpha:])", + 1, 0 }, + { "[ccccc(\?>c(\?{cccc[ccccwetoCei+)w&-+{,-142}[:alpha:]" + "PP66io4(|zkA=],,,,,,,,,,,,,,,,,,,,,Lx5Cx{d2bb}]{188}U~~~~~~~" + "~~~~~~~~~~~~~~~~})", + 0, 0 }, + { "Q|0\"[:d(\?:igit:]^{,-174})", 0, 0 }, + { "[^[(\?>rh])]", 0, 0 }, + { "[ees{{{{{{{{{{{{{{{{{bbbbbbb4`ml******(\?=****+])", 0, 0 }, + { "((hdG[((\?<=:dig(it:])[^[:alpha:]$(\?sxi:)x{11390}[(\?{:" + "upperword:]~)i 8[:blankcn[trl:(])]+{,-183}Zqp", + 2, 0 }, + { "Dd{D8`+DW={-[53,1(\?<=71}])", 0, 0 }, + { "[:(\?(alpha:][:punct:])", 0, 0 }, + { ".LLLLLLLLLLLLLLLLLLLLLLLLLLLL{}pP[:punct:]x0CZ{30,}!!!(!!!!!" + "!!!!!!!!!!!!!!!!!!!!==@77.%[:graph:]D)", + 1, 0 }, + { "[^[^[[r(\?#]){-237,}RRRRRRRRRRRRRRRRRRRRRRRR[^Rll(\?!(\?{" + "lllll]", + 0, 0 }, + { "()*ooooooooooooooooooooyyyyyyyyyyyyyyy", 1, 0 }, + { "{,4(}D)JJJJJJJJJJJJJJJJJJJJJJJJJ", 1, 0 }, + { "((b.D{}[:al[pha:]{64}]{})==========================[:alnum:]" + "h>77b)!Ab", + 2, 0 }, + { "([^[^[^oooooooooooooooooooooo][:space:][:punct:]PeniKe*~$" + "g\?${>[:lowerprint:]w))))))))))))))){}yyyyyyyyyyyyyyyyyy]pP." + "|QhZ]{,190})sssssssssssssr+=[:blankcntrl:]" + "WWWWWWWWWWWWWWWWWWWWW", + 1, 0 }, + { "([*(\?{})hhhhhhhhhhhhhhhh]G{,-170}QdErrrrrrrc-" + "jjjjjjjjjjjjjjjjjjjjn+{-130,-10})PpDS@Bee", + 1, 0 }, + { "([:b(\?=lankcntrl:]))T[:alnum:]{-224}ywt", 1, 0 }, + { "([633(\?<=333(\?<=3333333333(333333)^\?]aGA)[:digi(\?>(\?{t:" + "])$[[:space:][:xdigit:])|8T\?',_{171}{}{113}b\?5kAv0/" + "7{})`huh>xM]C8pYRz]s$Eu08)", + 1, 0 }, + { "-(pP)[:alnum:]$^", 1, 0 }, + { "[^x(\?{{17681}]P*)U(_t/8E_\"iN})3333333", 1, 0 }, + { "(([^([[r(\?=[[^^*kx$][:alpha:]:::[:::::[^[^::::::::((\?{\?{:" + ":]).^p[:space:]}){52}{}]W{}fn", + 2, 0 }, + { "[:(\?>punct:]Ef[:xdigit:]x{c07b}{-50}Z{129,}YL1T`\\A)x[:" + "punc(\?=t:]e[:xdigit:]2c6E46Y)+n ", + 0, 0 }, + { "[^(\?!{,-79}[:punct:]'|}>,)][:blankcntrl:]{-118,-231}{-119,-" + "50}:XXXXXXXXXXXXXXXXX-~{}$txlB)3KFL", + 0, 0 }, + { "[^(([^fccccccccccccccccccc(\?)])qcU$Q7|82\?{})", 2, 0 }, + { "[^yyyyyyyyyyyyyyyyyyyy(\?#yyyyyyyyyyya][:ascii:]\?)", 0, 0 }, + { "(([((\?{)EEEE(\?QQQQQQ(\?!QQQQQ][:digit:]\?))" + "99999999999999)[:digit:][:upperword:]b))PP{}{}", + 2, 0 }, + { "(K(c=B))", 2, 0 }, + { "(G`*s\?b[:g(raph:]))", 1, 0 }, + { "[^[([[[*QQQQQQQQQQQQQQQQ(\?=(\?=QQQQQQ(\?ddddddddddc{22,}iiiiiiiii(" + "iiiiiiiiiiiiiii(\?#iiiiiii[^i))\?\?\?\?\?\?]WWW)[:" + "lowerprint:])]{-60,202}+[:upperword:]f[:xdigit:][:alnum:]{,-" + "214})1~~~~~~~MMMMMMMMMMMMMMMMMM.", + 0, 0 }, + { "({-102,})A.", 1, 0 }, + { "[((((\?(\?#\?()))p\"JD.{}(\?>)))((\?{l(\?<=).'053][:" + "xdigit:]N+)})]WWWW%[:asc(\?{ii:]}))B[:alnum:]X){}s[:digit:]", + 0, 0 }, + { "x7&{139}WWWWWWWWWWWWWW[:blankcntr[^(\?~[^n@f`````````" + "````)````````P])Y,N{}{}]{}pXF@)", + 0, 0 }, + { "G[([(\?(^)$])P]^[:alnum:]){,-48}[:blankcntrl:]{}", 0, 0 }, + { "[[^[^f(\?=f(\?<=fffffff[^fffffffff[^fffffffff(\?<=fff]){-" + "194,150}fx{e5a4}V", + 0, 0 }, + { "9[:xdigit(\?{:]})", 0, 0 }, + { "[^([[(\?>()$xxxxxxxxxxxxxx[xxxxxxxxxxxxxxxx((\?=aA)s13]])pp[" + "(\?>pppppppppppppppp|{}){20,}]b)]{-179,183}{-204,}[:ascii:])" + "]-11111111{}{,132}qooooooooooooooooooo{}${}|9t", + 0, 0 }, + { "([^[{}]\"[^6]*-{,-106}{}u]BR~8WG,U-)[:blankcntrl:]", 1, 0 }, + { "[''''''''(''''''''''z])c", 0, 0 }, + { "[^[(\?>])[:alnum:]r[:alnum:]+{,215}D]", 0, 0 }, + { "([({,127}7Qr(\?:z)pPNev%}(\?msximsx:4(\?nn(\?:nnnnnnnn_U{}]E)):^" + "oooooooooooooooooooooooooooo)", + 1, 0 }, + { "[^(\?#)(\?!(([:alnum:]{252}{}})ffffffffffffl){}" + "A2r\?~ImE\"[:punct:]){}[:digit:]", + 2, 0 }, + { "([:blank[cntrl:]].t^P)", 1, 0 }, + { "[^[(\?:X])|rrrrrrrrrrrrrrrrrrrrrrrrrr*P]Q", 0, 0 }, + { "[[[^(\?{((\?15}]x{f779}ZZ,Wo)O[:alpha:][:lowerprint:]{" + "81,228}Q[:upperword:]", + 0, 0 }, + { "[[^[^()n[[[[[[[[[[[[^[[[[[[[[[[(\?: G)(\?{K![^m) " + "j(\?:C|((\?:n*Xlaa908:n$m,))[:xdigit:]x(\?{{1a5cd}" + "pppppppppppppp(\?(pppp)p(pQ)))" + "ddddddddddddddddddddddddddddddd]q[:alnum:(\?{]Ga})\?})@[:" + "lowerprint:]{,169}[:blankcntrl:][:graph:]]n{-76,}|U\"{,-54}" + "t]I{}{-64,-232}]\?].\?{-111,227}) " + "@hFp\?j=H$Wbu<{,209}De{,145}{206}-})[:blankcntrl:]", + 0, 0 }, + { "[^[^(LLLLLLLLLLLLLL[^L[L[:alpha:]3{,189}(\?#(\?>n){}^" + "EXXXXXXXXXXXXXXXXXXXXXXXXX]c*)^r=$WWWWWWWWWWWWW", + 0, 0 }, + { ")w###################", 0, 0 }, + { "{,121}[:d(\?(i)git:])E\?[:punct:]LLLLLLLLL[:ascii:]+", 0, + 0 }, + { "([]]]]]]]]]]]]][:space:]Jrt3o.]b)pwwwwwwwwwwwQfm~", 1, 0 }, + { "[+-{,-120}*(\?!()t*(\?(\?{>G)F)yd]V{}f<\?}){245}" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[:upperword:]", + 0, 0 }, + { "(DDDDDDDDDDDDDDDDDDDDDDDDDDDDDc[:space:][:pu[^nct:]{-11,12}[" + ":ascii:][:alpha:]{,155}P])", + 1, 0 }, + { "()ggggggg{-136,-21}", 1, 0 }, + { "([^((\?<=U\?)(\?=^^^^^^^^^^^[^^^^^^^^^^^^^///(\?#//[////////" + "////////////" + "(\?()#######b+]$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$^[:digit:])" + "\\U]Q8@}4d)\\U", + 1, 0 }, + { "A[:graph(\?::])-mo=U[:upperword:]" + "ttttttttttttttttttttttttttt", + 0, 0 }, + { "[^(((\?=\?im-m(sx:)c~~[^~~~~~~~~~~~~~(\?>~~~~~~~~~~~~~" + "SSSSSSSSSSSSSSSSSSSS]{51,}[:digit:]{,-179}N))kk[" + "kkkkkkkkkkkkkkg$)[(\?::punct:]zWl)]|)*", + 0, 0 }, + { "[((\?=()+A)][:graph:]x0B)[:graph:]", 0, 0 }, + { "(nR%B[:blankcntrl:]C=|en-[:digit:]n[:graph:]HHHH[HH]D\?%[:" + "digit:]MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.z(oF9zW8A7cfff(f))-[" + ":blankcntrl:][:blankcntrl:]A[:digit:])D{,-243}", + 3, 0 }, + { "([[()]]{,-251(})\?L)uw@", 2, 0 }, + { "\"|{(,-144})A.ooooooooo(ooooooFFFFFFFFFFFFF\?)n{,-18}", 2, + 0 }, + { "([^([(([[^([000000[0(0(\?!0(\?=0000000])45|E]", 1, 0 }, + { "[B[[[[[[[[[[[|{}*oKqv%(\?<=wsQ{1pMeK1^6%nLNqi<@ge][:punct:]=" + " M@* " + "D|NwL\\-" + "117\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"~" + "Qnd]h.O\"01x:[:alpha:]^){}D}\"", + 0, 0 }, + { "([[RRRRRRRRRRRRRRRRRRRRRRRRRRRRxpSrx{7d79}*oJ2`Ft{n1,3g:1H@" + "bT$D " + "&[n/" + "Cg)=ld@Ir{Fk>*4*`(\?>````````````````````(\?:`````.........." + "...........]]{,246})7 \"F4[^F|/g)]+e`rw@{,-69}H)", + 1, 0 }, + { "([(\?<=)X[:digit:]PP.[(\?#:((\?#\?#graph:])[:digit:][Q+)(N][" + ":alpha:]]f)[:graph:])+Elllllllllllllllll[:digit:]=)pP{uU-" + "20bzY|ZKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKt:])|l*KKKKKKKKKKKKKKKKK,,,,,,,[,,,s.{148,}" + "P33333][:lo(\?Q){,57}%[:digit:]" + "\?\?\?\?\?\?\?\?\?\?.[)]]d{)-49,}f)^O{,68})\?C", + 0, 0 }, + { "(}u])18621", 1, 0 }, + { "[:as(\?=cii:][^(\?=)(S-{.F-[:punct:]3-105^[:lowerprint:]" + "111111111111111111111111---)][:alnum:][:ascii:]JJJJJwHSk", + -1, 0 }, + { "[^3>>>>>>-sZ^^^^(\?>]Y[:di(\?(\?imxim:#git:]{-158,-102}[:" + "punct:]{}{87,})))[:upperword:]", + 0, 0 }, + { "[(\?{AjBBBBBBBBBBBBBBBBBBBBBBB[:upperword:]`'W)", + 0, 0 }, + { "[^([[()DN1[^][|]\?]{-104,}])[:space:]][:lowerprint:]r[:" + "alpha:].DU", + 0, 0 }, + { "[^((33333333333333333333333(\?<=3333333D))" + "kkkkkkkkkkkkkkkkkkkkkkk[k[:alpha:]])]X+", + 0, 0 }, + { "[({,-17})[@e{220,(\?#41}])]]{-213,-225}", 0, 0 }, + { "[[^(\?#[(\?:^[[(\?(^]))]])]vvvvvvvvvvvvvvvvvvvvv{,96}|m]{-" + "79,248}[:alpha:])", + 0, 0 }, + { "([[(\?imsisx:^}$,-[:al(\?>num:]Xqqqqqqqqqqqq{-185,154}]b#+T)" + "{-241,})A{-27}[(\?([\?()(\?#))]--R1rk^UnP.[(\?!:digit:]])^)[:upperword:]" + "{}0000000000000000000000000000000~U{-139,-19}z})RR(\?=R<]p'N~&.-})6]", 0, 0 }, + { "[^\?[^(\?(lFt]).[^7Q-])kkkkkkkkkkkk]XTFy\"1Deiv!,'xVK", 0, + 0 }, + { "[^$[^[:xdigit:](\?{*{245,99}h8v(\?!)]]u)Z[:punct:]})[:alnum:" + "]+|[:blankcntrl:]u{}[:lowerprint:]+bBJ4+k-v{-116}", + 0, 0 }, + { "S)f{,180}[:graph:]&{12,244}", 0, 0 }, + { "(([[(.()[^^{80(\?>(\?<=,235})ddddddddd[^ddddddddd(\?<=d.__B{" + "36}````````````````(\?:```(\?>```````,,,,,,,(\?:,,)P$U,[:" + "xdigit:])zzzzzzzzzzzzz]UUUU[uB]n<&[(:ascii:].][:alnum:])\?S]" + "{})d{138,}s9========[:lowerprint:]]OOOOOOOOOOOOOOO|" + "yyyyyyyyyyyyyyy$LZ[:lowerprint:]EEEEEEE[:ascii:][:punct:]" + "VpP^{-48}D){,46}x))2P))a[:lowerprint:]r", + 2, 0 }, + { "[^(((\?555(\?owerp(rint:]])]*", + 0, 0 }, + { "Au)khgzAfXIZoZ=g[:digit:]){,186}Upvf=x<]Tbd5Rq\?.", 0, 0 }, + { "b{-176,}B^[:bla(\?(>>>>>>>>>>>>(>>>>>>>>D)Ix{(1(\?imxmsx:762)c})" + ")A)[[[[[[[[[[[[[[5Rp]DDDDDDDDDDDDDDDDDDDD]Us+\\w[:digit:]{-" + "47}[:xdigit:][:blankcntrl:])ddddddddddddddd[^ddddddddddddd[:" + "digit:]|]]*{-165,-230}{-212}{53,}]\?", + 0, 0 }, + { "[^[^]]|[:(\?:alnum:])}}}}}}}}}}}}}}}}}}}}", 0, 0 }, + { "VVVVVVVVVVVVVVVVVVVVVVVVVVVV[:d(i(\?#git:])){{{{{{[:digit:]" + "ZfQ55555555{}Z", + 0, 0 }, + { "[L][:blankcnt(\?((\?=rl:(\?=]){-35,[^}){)eJb>>>>>>>>>>>>>>>>" + ">>>>>>$ [:xdigit:]l0Tv2Tw2@C[:space:]Zc/{*)>]N3j~.dMBBBB", + 0, 0 }, + { "[[^(\?>(([]))])[:graph:]]{65,}as#Q:lQ", 0, 0 }, + { "[^[fPPUUUUUUUUUUU(\?#UUU[^UUUUUU(\?<=" + "UUUUUUUUUGGGGGGGGGGGGGGGGGGG((\?{\?=GGGGGG.MK))+]+)&UxFW)" + "rwv\?@D.", + 0, 0 }, + { "{-(60,})m", 1, 0 }, + { "b[(])^w", 0, 0 }, + { "[][^qVs(\?:(p])X)\?'", 0, 0 }, + { "()8", 1, 0 }, + { "(t[:punc[^t:(\?{][:blankcntrl:])})[^8\?]z*]", 1, 0 }, + { "[:lowerprint:])[:graph:]lppppppppppppppppppppppppppppf", 0, + 0 }, + { "[:alph(a:])[:ascii:]g +z-Bc-U{,%Gk", 0, 0 }, + { "u[:graph:(\?=]*)W:::", 0, 0 }, + { "([:alnum(:])l)", 1, 0 }, + { "[[[}}}}}}}}(\?)(\?{,)At]%M9FSq5)EB", 1, 0 }, + { "(}````````````````(``{210,})[:(\?#space:]P[:digit:])PP.{-" + "227,}$pK~mm ImR|{,51}[:alnum:]<)[:alpha:]", + 2, 0 }, + { "[^(\?<=])[:digit:]", 0, 0 }, + { "[^'''''''{(\?:178,}e{,16}$QQQQQQQQQQQQQQQQQQQQQQQ$])", 0, + 0 }, + { "[^(\?>@K*)(\?#d18]{78,}B)[:digit:]{-193,}=wg{,59}", 0, 0 }, + { "[^.{156,}!(\?<=!!!!!!!!!!!!!!(\?{!(\?(!!!!!!!!!!!!!)})" + "TTTTTTTTTTTTTTTTTTTTTTTTTTTTT[^}}}}}}}}}}}})}}}}}}}}}}}}}]])" + "{}^L#%-{}FC", + 0, 0 }, + { "(eeeee{-169,-100}-fa[:upperword:]N)$Nellllllllllllll", 1, + 0 }, + { "[[(\?!())\?[(\?!:alnum:]e{,28}M])[:punct:]" + "CCCCCCCCCCCCCCCCCCCC]{-150,}{-167}", + 0, 0 }, + { "[[@[@(\?#@[@]P]Z{')]{-186,117}]+)7f-", 0, 0 }, + { "\\Q+kD}]AEM)u ", 0, 0 }, + { "([(\?{(\?=:::::::::::::&){,210}]^})P{-31,}8[:space:]C[:" + "alnum:][:a(scii:]z|[:upperword:])[:alnum:][:graph:])zr~Zk", + 1, 0 }, + { ".[:space:]e[:g(\?{(\?{raph:]})})@@@@@@@@@@@@@wb|~k", 0, 0 }, + { "()ooooooooo\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"[:graph:]", 1, + 0 }, + { "[^64h(\?(@Eyw][:xdi[git:]pP%%%%%u(uuu[:up[perword:]`8Utdh{)}" + "]]))lW[:punct:]W.hhhhhhhhhhhhhhhhhhhhhhhh'm<<}O8`ZXtG.$", + 1, 0 }, + { "BPP[:digit:]bbbbbbbbbbb(bb)S+[:alnum:]", 1, 0 }, + { "um.[:ascii((\?#\?!:])*)+KKKKKKKKKKKKKKKKKKKKKKKKKS.=,eDl", + -1, 0 }, + { "(()[^])e{-241,}", -1, 0 }, + { "()[:alpha:]rliiiiiiii[:alnum:]Mb*QW9N.>\?{115,}&u*j", -1, + 0 }, + { "()[]p", -1, 0 }, + { "(I[^]pfL)$[:punct:]", -1, 0 }, + { "([])>>>>>>>>>>[:alnum:]", -1, 0 }, + { "([])O\\\\\\\\\\\\\\fffffffffffffffffffffff=s6jCZy/" + "b+ir2'*{151,}", + -1, 0 }, + { "([])nnnnnnnnnnnnnnnnnnnnnnnnnn[:xdigit:]^N$f", -1, 0 }, + { "([]M)[:lowerprint:]a(pg$Z[:punct:])77777777777.", -1, 0 }, + { "([]XXXXXXXXXXXXXXXXXXXXXX-===========)", -1, 0 }, + { "([]lkX{-224}[:blankcntrl:]$gPKIZlSC#F@XX " + "I'^}{234}yZm)uuuuuuuuuuuuuuuuuuuuuurS", + -1, 0 }, + { "([^0kYkg9])IIIIIIIIIIIIIIIIIIIIII/" + "{(192,-118}l+FoSD6\?A)c[:xdigit:]`````````````````e-{-4,-" + "170}x{4620}Z[:upperword:]", + -1, 0 }, + { "([^[^[^()(\?>){}B]XYF+#[:alpha:]{-85((,-55[^}t]n).{,-33}]](" + "bQJ!|O+{175,})RFh)Z+^.{137,}:VpP[:alpha:]-MceqVVkkkk(" + "kkkkkkkkkkkkkkkkkk)" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?{-" + "115,-67})``````````````````````````````", + -1, 0 }, + { "([^]EzU[:alnum:]+^^^^^^^^^^^^^^^^^^^)[:xdigit:]HHHHHHHH$" + "66666666666666666666666666666666UUUUUUUUUUUUUUUUUUUUL{}iiii{" + "-76}X", + -1, 0 }, + { "([^]~~~~~~~~~~{240,})]NOp", -1, 0 }, + { "(sb)[:digit:]VVVVVVVVx{9569}52,|]", -1, 0 }, + { "(x{19762}){}", -1, 0 }, + { "-[:xdigit:][]", -1, 0 }, + { "121|", -1, 0 }, + { "141[:xdigit:][:lowerprint:]{24}{59,191}[:digit:]/", -1, 0 }, + { "G[^],,,,,,,,,,,,,+\"DiX", -1, 0 }, + { "Gm(ho9:\"8{-188,-200}Z[:blankcntrl:]{,171}" + "\?\?\?\?\?\?\?\?\?\?\?[:blankcntrl:]LLLLLLLLLLLLLLLLLLLLLLL{" + "}^[:graph:][:blankc(\?#ntrl:])w", + -1, 0 }, + { "N\"\"\"\"\"\"\"-------------------------|[:alnum:]" + "AAAAAAAAAAAAAAAAAAAAf\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?", + -1, 0 }, + { "U{-30,}^\?\?\?", -1, 0 }, + { "W^*04rAY(Ee*>[^o3[]]_)", -1, 0 }, + { "X[^]}*C[:alnum:]", -1, 0 }, + { "[${,-3}]+^\?[|x8A|][:space:]'''''['''''" + "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJyl}.Y7G]", + -1, 0 }, + { "[()&[&&&]\?\?[" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?" + "pg%k8ug`Wqk4|NR{h[CK5Ez=]jHpQw&`{:]{,91}D", + -1, 0 }, + { "[(\?#(\?:)[)([\?>)(\?>(\?:[:alnum:])]G]{85}[^)w]N]gYrUs|", + -1, 0 }, + { "[(\?<=)[:digit:]\?]{152,}VR|", -1, 0 }, + { "[****(\?>**********(\?))TTTTTTTTTTTTTTTTTTTTTTT)[:punct:][:digit:" + "]]GGGGGGGGGGGGGGGGGGGGG,]|.{-224}{96}{239,}1", + -1, 0 }, + { "[[^^PP]{,-222}{182}{141}]zFD}-.", -1, 0 }, + { "[] Hn&[:xdigit:][:upperword:]f", -1, 0 }, + { "[]$.B", -1, 0 }, + { "[]&&&&&&&&&&&&&&&&&&&&&&&", -1, 0 }, + { "[]()[:xdigit:]er063{132,140}$", -1, 0 }, + { "[]+1434", -1, 0 }, + { "[]-", -1, 0 }, + { "[]-#yyK", -1, 0 }, + { "[]-(S$5)AxbdTKO[:alnum:]", -1, 0 }, + { "[]2883", -1, 0 }, + { "[]2dhd-[:alpha:]" + "sssssssssssssssss55555555555555555555555555555555Z[:punct:]", + -1, 0 }, + { "[]4", -1, 0 }, + { "[]44444444444444444G", -1, 0 }, + { "[]\?", -1, 0 }, + { "[]A", -1, 0 }, + { "[]Gap8bc", -1, 0 }, + { "[]OOOO", -1, 0 }, + { "[]PP", -1, 0 }, + { "[]QQ", -1, 0 }, + { "[]WaFaGO,o", -1, 0 }, + { "[]Z", -1, 0 }, + { "[][:alpha:]|[:digit:]Ls$I-Ff~+xA3e", -1, 0 }, + { "[][:ascii:]-218", -1, 0 }, + { "[][:ascii:]N}}}}}}}}}}}}}}}-{137,}8682", -1, 0 }, + { "[][:lowerprint:]Ur", -1, 0 }, + { "[][:space:]15097", -1, 0 }, + { "[][:xdigit:]", -1, 0 }, + { "[]dpSSSSSSSS", -1, 0 }, + { "[]e13768", -1, 0 }, + { "[]gT", -1, 0 }, + { "[]h", -1, 0 }, + { "[]n", -1, 0 }, + { "[]vvvvvvvvvvvvvvvvvvvvvvvvvv*[:xdigit:]", -1, 0 }, + { "[]{,-212}1111111111111111111C3821", -1, 0 }, + { "[]{-128,}hc", -1, 0 }, + { "[]{-181,}&[:xdigit:].\?}}}}}}}}}}}}}}}}}}}}}}", -1, 0 }, + { "[]{}F&}i`7|ZAH", -1, 0 }, + { "[^(\?())u{196,}pP][r^ndddddddddddddddddddddd]{31,246}\?J", + -1, 0 }, + { "[^.ii.1-S]lwwwwwwwwwwwwwwwwww[^wwwwwwwwwwwwww[:alnum:]DOpP+<" + "N][^]44{179}{-194,56}", + -1, 0 }, + { "[^2[:alnum:]]\?t\?\?", -1, 0 }, + { "[^[((\?{[^^<<<<(\?(\?%fffffffffff", + -1, 0 }, + { "aW|", -1, 0 }, + { "cT{}[]C^r2``tm", -1, 0 }, + { "kkkkkkkkkkkkkkkkkkkkkkk[:blankcntrl:]|{}3{26,}{151,}[:punct:" + "]JJJlH$gP%(2WUE%%%%%%%%%%%%%%%%%%%%a){ibf{}\?", + -1, 0 }, + { "lZ\?\?\?\?\?\?\?\?\?\?\?-P2eZt[:punct:]", -1, 0 }, + { "vF3qn[^]N.", -1, 0 }, + { "wwwwwwwwwwwwww{-176,}275[^]>." + "UUUUUUUUUUUUUUUUUUUUeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee2$Yd", + -1, 0 }, + { "{-197,223}bf]]]]]]]]]]\?&}/s\?\?~c", -1, 0 }, + { "{-37,}EpP|", -1, 0 }, + { "{}@]a[][:xdigit:]z{a", -1, 0 }, + { "}02|", -1, 0 }, + { "}}}}}}}}}(}}){}[llll]^N|", -1, 0 }, + }; + unsigned int i; + int r; + + UNUSED(state); + +#ifdef HAVE_REGEX_H + /* + * Check if we get the expected response. + */ + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + regex_t preg; + + memset(&preg, 0, sizeof(preg)); + r = regcomp(&preg, tests[i].expression, REG_EXTENDED); + if (((r != 0 && tests[i].expect != -1) || + (r == 0 && tests[i].expect == -1)) && + !tests[i].exception) + { + } else if (r == 0 && + preg.re_nsub != (unsigned int)tests[i].expect && + !tests[i].exception) + { + tests[i].expect = preg.re_nsub; + } + if (r == 0) { + regfree(&preg); + } + } +#endif /* ifdef HAVE_REGEX_H */ + + /* + * Check if we get the expected response. + */ + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + r = isc_regex_validate(tests[i].expression); + if (r != tests[i].expect) { + print_error("# %s -> %d expected %d\n", + tests[i].expression, r, tests[i].expect); + } + assert_int_equal(r, tests[i].expect); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(regex_validate) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/result_test.c b/tests/isc/result_test.c new file mode 100644 index 0000000..cec195b --- /dev/null +++ b/tests/isc/result_test.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include + +#include + +/* convert result to identifier string */ +ISC_RUN_TEST_IMPL(isc_result_toid) { + const char *id; + + UNUSED(state); + + id = isc_result_toid(ISC_R_SUCCESS); + assert_string_equal("ISC_R_SUCCESS", id); + + id = isc_result_toid(ISC_R_FAILURE); + assert_string_equal("ISC_R_FAILURE", id); +} + +/* convert result to description string */ +ISC_RUN_TEST_IMPL(isc_result_totext) { + const char *str; + + UNUSED(state); + + str = isc_result_totext(ISC_R_SUCCESS); + assert_string_equal("success", str); + + str = isc_result_totext(ISC_R_FAILURE); + assert_string_equal("failure", str); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_result_toid) +ISC_TEST_ENTRY(isc_result_totext) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/safe_test.c b/tests/isc/safe_test.c new file mode 100644 index 0000000..a3f01fe --- /dev/null +++ b/tests/isc/safe_test.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include + +#include + +/* test isc_safe_memequal() */ +ISC_RUN_TEST_IMPL(isc_safe_memequal) { + UNUSED(state); + + assert_true(isc_safe_memequal("test", "test", 4)); + assert_true(!isc_safe_memequal("test", "tesc", 4)); + assert_true( + isc_safe_memequal("\x00\x00\x00\x00", "\x00\x00\x00\x00", 4)); + assert_true( + !isc_safe_memequal("\x00\x00\x00\x00", "\x00\x00\x00\x01", 4)); + assert_true( + !isc_safe_memequal("\x00\x00\x00\x02", "\x00\x00\x00\x00", 4)); +} + +/* test isc_safe_memwipe() */ +ISC_RUN_TEST_IMPL(isc_safe_memwipe) { + UNUSED(state); + + /* These should pass. */ + isc_safe_memwipe(NULL, 0); + isc_safe_memwipe((void *)-1, 0); + + /* + * isc_safe_memwipe(ptr, size) should function same as + * memset(ptr, 0, size); + */ + { + char buf1[4] = { 1, 2, 3, 4 }; + char buf2[4] = { 1, 2, 3, 4 }; + + isc_safe_memwipe(buf1, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + + assert_int_equal(memcmp(buf1, buf2, sizeof(buf1)), 0); + } + + /* + * Boundary test. + */ + { + char buf1[4] = { 1, 2, 3, 4 }; + char buf2[4] = { 1, 2, 3, 4 }; + + /* + * We wipe 3 elements on purpose, keeping the 4th in + * place. + */ + isc_safe_memwipe(buf1, 3); + memset(buf2, 0, 3); + + assert_int_equal(memcmp(buf1, buf2, sizeof(buf1)), 0); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(isc_safe_memequal) +ISC_TEST_ENTRY(isc_safe_memwipe) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/siphash_test.c b/tests/isc/siphash_test.c new file mode 100644 index 0000000..5e93980 --- /dev/null +++ b/tests/isc/siphash_test.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include + +#include "siphash.c" + +#include + +const uint8_t vectors_sip64[64][8] = { + { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72 }, + { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74 }, + { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d }, + { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85 }, + { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf }, + { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18 }, + { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb }, + { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab }, + { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93 }, + { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e }, + { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a }, + { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4 }, + { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75 }, + { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14 }, + { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7 }, + { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1 }, + { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f }, + { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69 }, + { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b }, + { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb }, + { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe }, + { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0 }, + { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93 }, + { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8 }, + { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8 }, + { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc }, + { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17 }, + { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f }, + { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde }, + { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6 }, + { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad }, + { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32 }, + { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71 }, + { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7 }, + { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12 }, + { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15 }, + { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31 }, + { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02 }, + { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca }, + { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a }, + { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e }, + { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad }, + { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18 }, + { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4 }, + { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9 }, + { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9 }, + { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb }, + { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0 }, + { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6 }, + { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7 }, + { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee }, + { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1 }, + { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a }, + { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81 }, + { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f }, + { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24 }, + { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7 }, + { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea }, + { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60 }, + { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66 }, + { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c }, + { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f }, + { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5 }, + { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95 } +}; + +const uint8_t vectors_hsip32[64][4] = { + { 0xa9, 0x35, 0x9f, 0x5b }, { 0x27, 0x47, 0x5a, 0xb8 }, + { 0xfa, 0x62, 0xa6, 0x03 }, { 0x8a, 0xfe, 0xe7, 0x04 }, + { 0x2a, 0x6e, 0x46, 0x89 }, { 0xc5, 0xfa, 0xb6, 0x69 }, + { 0x58, 0x63, 0xfc, 0x23 }, { 0x8b, 0xcf, 0x63, 0xc5 }, + { 0xd0, 0xb8, 0x84, 0x8f }, { 0xf8, 0x06, 0xe7, 0x79 }, + { 0x94, 0xb0, 0x79, 0x34 }, { 0x08, 0x08, 0x30, 0x50 }, + { 0x57, 0xf0, 0x87, 0x2f }, { 0x77, 0xe6, 0x63, 0xff }, + { 0xd6, 0xff, 0xf8, 0x7c }, { 0x74, 0xfe, 0x2b, 0x97 }, + { 0xd9, 0xb5, 0xac, 0x84 }, { 0xc4, 0x74, 0x64, 0x5b }, + { 0x46, 0x5b, 0x8d, 0x9b }, { 0x7b, 0xef, 0xe3, 0x87 }, + { 0xe3, 0x4d, 0x10, 0x45 }, { 0x61, 0x3f, 0x62, 0xb3 }, + { 0x70, 0xf3, 0x67, 0xfe }, { 0xe6, 0xad, 0xb8, 0xbd }, + { 0x27, 0x40, 0x0c, 0x63 }, { 0x26, 0x78, 0x78, 0x75 }, + { 0x4f, 0x56, 0x7b, 0x5f }, { 0x3a, 0xb0, 0xe6, 0x69 }, + { 0xb0, 0x64, 0x40, 0x00 }, { 0xff, 0x67, 0x0f, 0xb4 }, + { 0x50, 0x9e, 0x33, 0x8b }, { 0x5d, 0x58, 0x9f, 0x1a }, + { 0xfe, 0xe7, 0x21, 0x12 }, { 0x33, 0x75, 0x32, 0x59 }, + { 0x6a, 0x43, 0x4f, 0x8c }, { 0xfe, 0x28, 0xb7, 0x29 }, + { 0xe7, 0x5c, 0xc6, 0xec }, { 0x69, 0x7e, 0x8d, 0x54 }, + { 0x63, 0x68, 0x8b, 0x0f }, { 0x65, 0x0b, 0x62, 0xb4 }, + { 0xb6, 0xbc, 0x18, 0x40 }, { 0x5d, 0x07, 0x45, 0x05 }, + { 0x24, 0x42, 0xfd, 0x2e }, { 0x7b, 0xb7, 0x86, 0x3a }, + { 0x77, 0x05, 0xd5, 0x48 }, { 0xd7, 0x52, 0x08, 0xb1 }, + { 0xb6, 0xd4, 0x99, 0xc8 }, { 0x08, 0x92, 0x20, 0x2e }, + { 0x69, 0xe1, 0x2c, 0xe3 }, { 0x8d, 0xb5, 0x80, 0xe5 }, + { 0x36, 0x97, 0x64, 0xc6 }, { 0x01, 0x6e, 0x02, 0x04 }, + { 0x3b, 0x85, 0xf3, 0xd4 }, { 0xfe, 0xdb, 0x66, 0xbe }, + { 0x1e, 0x69, 0x2a, 0x3a }, { 0xc6, 0x89, 0x84, 0xc0 }, + { 0xa5, 0xc5, 0xb9, 0x40 }, { 0x9b, 0xe9, 0xe8, 0x8c }, + { 0x7d, 0xbc, 0x81, 0x40 }, { 0x7c, 0x07, 0x8e, 0xc5 }, + { 0xd4, 0xe7, 0x6c, 0x73 }, { 0x42, 0x8f, 0xcb, 0xb9 }, + { 0xbd, 0x83, 0x99, 0x7a }, { 0x59, 0xea, 0x4a, 0x74 } +}; + +ISC_RUN_TEST_IMPL(isc_siphash24) { + UNUSED(state); + + uint8_t in[64], out[8], key[16]; + for (size_t i = 0; i < ARRAY_SIZE(key); i++) { + key[i] = i; + } + + for (size_t i = 0; i < ARRAY_SIZE(in); i++) { + in[i] = i; + isc_siphash24(key, in, i, out); + assert_memory_equal(out, vectors_sip64[i], 8); + } +} + +ISC_RUN_TEST_IMPL(isc_halfsiphash24) { + UNUSED(state); + + uint8_t in[64], out[4], key[16]; + for (size_t i = 0; i < ARRAY_SIZE(key); i++) { + key[i] = i; + } + + for (size_t i = 0; i < ARRAY_SIZE(in); i++) { + in[i] = i; + isc_halfsiphash24(key, in, i, out); + assert_memory_equal(out, vectors_hsip32[i], 4); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_siphash24) +ISC_TEST_ENTRY(isc_halfsiphash24) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/sockaddr_test.c b/tests/isc/sockaddr_test.c new file mode 100644 index 0000000..c65ed76 --- /dev/null +++ b/tests/isc/sockaddr_test.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include + +/* test sockaddr hash */ +ISC_RUN_TEST_IMPL(sockaddr_hash) { + isc_sockaddr_t addr; + struct in_addr in; + struct in6_addr in6; + unsigned int h1, h2, h3, h4; + int ret; + + UNUSED(state); + + in.s_addr = inet_addr("127.0.0.1"); + isc_sockaddr_fromin(&addr, &in, 1); + h1 = isc_sockaddr_hash(&addr, true); + h2 = isc_sockaddr_hash(&addr, false); + assert_int_not_equal(h1, h2); + + ret = inet_pton(AF_INET6, "::ffff:127.0.0.1", &in6); + assert_int_equal(ret, 1); + isc_sockaddr_fromin6(&addr, &in6, 1); + h3 = isc_sockaddr_hash(&addr, true); + h4 = isc_sockaddr_hash(&addr, false); + assert_int_equal(h1, h3); + assert_int_equal(h2, h4); +} + +/* test isc_sockaddr_isnetzero() */ +ISC_RUN_TEST_IMPL(sockaddr_isnetzero) { + isc_sockaddr_t addr; + struct in_addr in; + struct in6_addr in6; + bool r; + + size_t i; + struct { + const char *string; + bool expect; + } data4[] = { + { "0.0.0.0", true }, { "0.0.0.1", true }, + { "0.0.1.0", true }, { "0.1.0.0", true }, + { "1.0.0.0", false }, { "0.0.0.127", true }, + { "0.0.0.255", true }, { "127.0.0.1", false }, + { "255.255.255.255", false }, + }; + /* + * Mapped addresses are currently not netzero. + */ + struct { + const char *string; + bool expect; + } data6[] = { + { "::ffff:0.0.0.0", false }, + { "::ffff:0.0.0.1", false }, + { "::ffff:0.0.0.127", false }, + { "::ffff:0.0.0.255", false }, + { "::ffff:127.0.0.1", false }, + { "::ffff:255.255.255.255", false }, + }; + + UNUSED(state); + + for (i = 0; i < sizeof(data4) / sizeof(data4[0]); i++) { + in.s_addr = inet_addr(data4[i].string); + isc_sockaddr_fromin(&addr, &in, 1); + r = isc_sockaddr_isnetzero(&addr); + assert_int_equal(r, data4[i].expect); + } + + for (i = 0; i < sizeof(data6) / sizeof(data6[0]); i++) { + int ret = inet_pton(AF_INET6, data6[i].string, &in6); + assert_int_equal(ret, 1); + isc_sockaddr_fromin6(&addr, &in6, 1); + r = isc_sockaddr_isnetzero(&addr); + assert_int_equal(r, data6[i].expect); + } +} + +/* + * test that isc_sockaddr_eqaddrprefix() returns true when prefixes of a + * and b are equal, and false when they are not equal + */ +ISC_RUN_TEST_IMPL(sockaddr_eqaddrprefix) { + struct in_addr ina_a; + struct in_addr ina_b; + struct in_addr ina_c; + isc_sockaddr_t isa_a; + isc_sockaddr_t isa_b; + isc_sockaddr_t isa_c; + + UNUSED(state); + + assert_true(inet_pton(AF_INET, "194.100.32.87", &ina_a) >= 0); + assert_true(inet_pton(AF_INET, "194.100.32.80", &ina_b) >= 0); + assert_true(inet_pton(AF_INET, "194.101.32.87", &ina_c) >= 0); + + isc_sockaddr_fromin(&isa_a, &ina_a, 0); + isc_sockaddr_fromin(&isa_b, &ina_b, 42); + isc_sockaddr_fromin(&isa_c, &ina_c, 0); + + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 0)); + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 29)); + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 8)); + + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 30)); + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 32)); + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 16)); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(sockaddr_hash) +ISC_TEST_ENTRY(sockaddr_isnetzero) +ISC_TEST_ENTRY(sockaddr_eqaddrprefix) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/stats_test.c b/tests/isc/stats_test.c new file mode 100644 index 0000000..a475323 --- /dev/null +++ b/tests/isc/stats_test.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include + +#include + +/* test stats */ +ISC_RUN_TEST_IMPL(isc_stats_basic) { + isc_stats_t *stats = NULL; + isc_result_t result; + + UNUSED(state); + + result = isc_stats_create(mctx, &stats, 4); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_stats_ncounters(stats), 4); + + /* Default all 0. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + assert_int_equal(isc_stats_get_counter(stats, i), 0); + } + + /* Test increment. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_increment(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 1); + isc_stats_increment(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 2); + } + + /* Test decrement. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_decrement(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 1); + isc_stats_decrement(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 0); + } + + /* Test set. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_set(stats, i, i); + assert_int_equal(isc_stats_get_counter(stats, i), i); + } + + /* Test update if greater. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_update_if_greater(stats, i, i); + assert_int_equal(isc_stats_get_counter(stats, i), i); + isc_stats_update_if_greater(stats, i, i + 1); + assert_int_equal(isc_stats_get_counter(stats, i), i + 1); + } + + /* Test resize. */ + isc_stats_resize(&stats, 3); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 4); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 5); + assert_int_equal(isc_stats_ncounters(stats), 5); + + /* Existing counters are retained */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + uint32_t expect = i + 1; + if (i == 4) { + expect = 0; + } + assert_int_equal(isc_stats_get_counter(stats, i), expect); + } + + isc_stats_detach(&stats); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_stats_basic) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/symtab_test.c b/tests/isc/symtab_test.c new file mode 100644 index 0000000..795a455 --- /dev/null +++ b/tests/isc/symtab_test.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +static void +undefine(char *key, unsigned int type, isc_symvalue_t value, void *arg) { + UNUSED(arg); + + assert_int_equal(type, 1); + isc_mem_free(mctx, key); + isc_mem_free(mctx, value.as_pointer); +} + +/* test symbol table growth */ +ISC_RUN_TEST_IMPL(symtab_grow) { + isc_result_t result; + isc_symtab_t *st = NULL; + isc_symvalue_t value; + isc_symexists_t policy = isc_symexists_reject; + int i; + + UNUSED(state); + + result = isc_symtab_create(mctx, 3, undefine, NULL, false, &st); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(st); + + /* Nothing should be in the table yet */ + + /* + * Put 1024 entries in the table (this should necessate + * regrowing the hash table several times + */ + for (i = 0; i < 1024; i++) { + char str[16], *key; + + snprintf(str, sizeof(str), "%04x", i); + key = isc_mem_strdup(mctx, str); + assert_non_null(key); + value.as_pointer = isc_mem_strdup(mctx, str); + assert_non_null(value.as_pointer); + result = isc_symtab_define(st, key, 1, value, policy); + assert_int_equal(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) { + undefine(key, 1, value, NULL); + } + } + + /* + * Try to put them in again; this should fail + */ + for (i = 0; i < 1024; i++) { + char str[16], *key; + + snprintf(str, sizeof(str), "%04x", i); + key = isc_mem_strdup(mctx, str); + assert_non_null(key); + value.as_pointer = isc_mem_strdup(mctx, str); + assert_non_null(value.as_pointer); + result = isc_symtab_define(st, key, 1, value, policy); + assert_int_equal(result, ISC_R_EXISTS); + undefine(key, 1, value, NULL); + } + + /* + * Retrieve them; this should succeed + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_lookup(st, str, 0, &value); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(str, (char *)value.as_pointer); + } + + /* + * Undefine them + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_undefine(st, str, 1); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* + * Retrieve them again; this should fail + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_lookup(st, str, 0, &value); + assert_int_equal(result, ISC_R_NOTFOUND); + } + + isc_symtab_destroy(&st); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(symtab_grow) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/task_test.c b/tests/isc/task_test.c new file mode 100644 index 0000000..973ecc9 --- /dev/null +++ b/tests/isc/task_test.c @@ -0,0 +1,1408 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netmgr/uv-compat.h" + +#include + +/* Set to true (or use -v option) for verbose output */ +static bool verbose = false; + +static isc_mutex_t lock; +static isc_condition_t cv; + +atomic_int_fast32_t counter; +static int active[10]; +static atomic_bool done; + +static int +_setup(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + workers = 0; + setup_managers(state); + + return (0); +} + +static int +_setup2(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + /* Two worker threads */ + workers = 2; + setup_managers(state); + + return (0); +} + +static int +_setup4(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + /* Four worker threads */ + workers = 4; + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + + isc_condition_destroy(&cv); + isc_mutex_destroy(&lock); + + return (0); +} + +static void +set(isc_task_t *task, isc_event_t *event) { + atomic_int_fast32_t *value = (atomic_int_fast32_t *)event->ev_arg; + + UNUSED(task); + + isc_event_free(&event); + atomic_store(value, atomic_fetch_add(&counter, 1)); +} + +#include + +static void +set_and_drop(isc_task_t *task, isc_event_t *event) { + atomic_int_fast32_t *value = (atomic_int_fast32_t *)event->ev_arg; + + UNUSED(task); + + isc_event_free(&event); + LOCK(&lock); + atomic_store(value, atomic_fetch_add(&counter, 1)); + UNLOCK(&lock); +} + +/* Create a task */ +ISC_RUN_TEST_IMPL(create_task) { + isc_result_t result; + isc_task_t *task = NULL; + + UNUSED(state); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_destroy(&task); + assert_null(task); +} + +/* Process events */ +ISC_RUN_TEST_IMPL(all_events) { + isc_result_t result; + isc_task_t *task = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b; + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, 0); + atomic_init(&b, 0); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* First event */ + event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST, set, &a, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), 0); + isc_task_send(task, &event); + + event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST, set, &b, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), 0); + isc_task_send(task, &event); + + while ((atomic_load(&a) == 0 || atomic_load(&b) == 0) && i++ < 5000) { + uv_sleep(1); + } + + assert_int_not_equal(atomic_load(&a), 0); + assert_int_not_equal(atomic_load(&b), 0); + + isc_task_destroy(&task); + assert_null(task); +} + +/* Privileged events */ +ISC_RUN_TEST_IMPL(privileged_events) { + isc_result_t result; + isc_task_t *task1 = NULL, *task2 = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b, c, d, e; + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, -1); + atomic_init(&b, -1); + atomic_init(&c, -1); + atomic_init(&d, -1); + atomic_init(&e, -1); + + /* + * Pause the net/task manager so we can fill up the work + * queue without things happening while we do it. + */ + isc_nm_pause(netmgr); + isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task1, "privileged", NULL); + assert_false(isc_task_getprivilege(task1)); + isc_task_setprivilege(task1, true); + assert_true(isc_task_getprivilege(task1)); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task2, "normal", NULL); + assert_false(isc_task_getprivilege(task2)); + + /* First event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &a, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), -1); + isc_task_send(task1, &event); + + /* Second event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, set, &b, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), -1); + isc_task_send(task2, &event); + + /* Third event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &c, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&c), -1); + isc_task_send(task1, &event); + + /* Fourth event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &d, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&d), -1); + isc_task_send(task1, &event); + + /* Fifth event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, set, &e, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&e), -1); + isc_task_send(task2, &event); + + isc_nm_resume(netmgr); + + /* We're waiting for *all* variables to be set */ + while ((atomic_load(&a) < 0 || atomic_load(&b) < 0 || + atomic_load(&c) < 0 || atomic_load(&d) < 0 || + atomic_load(&e) < 0) && + i++ < 5000) + { + isc_test_nap(1000); + } + + /* + * We can't guarantee what order the events fire, but + * we do know the privileged tasks that set a, c, and d + * would have fired first. + */ + assert_true(atomic_load(&a) <= 3); + assert_true(atomic_load(&c) <= 3); + assert_true(atomic_load(&d) <= 3); + + /* ...and the non-privileged tasks that set b and e, last */ + assert_true(atomic_load(&b) > 3); + assert_true(atomic_load(&e) > 3); + + assert_int_equal(atomic_load(&counter), 6); + + isc_task_setprivilege(task1, false); + assert_false(isc_task_getprivilege(task1)); + + isc_task_destroy(&task1); + assert_null(task1); + isc_task_destroy(&task2); + assert_null(task2); +} + +/* + * Edge case: this tests that the task manager behaves as expected when + * we explicitly set it into normal mode *while* running privileged. + */ +ISC_RUN_TEST_IMPL(privilege_drop) { + isc_result_t result; + isc_task_t *task1 = NULL, *task2 = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b, c, d, e; /* non valid states */ + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, -1); + atomic_init(&b, -1); + atomic_init(&c, -1); + atomic_init(&d, -1); + atomic_init(&e, -1); + + /* + * Pause the net/task manager so we can fill up the work queue + * without things happening while we do it. + */ + isc_nm_pause(netmgr); + isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task1, "privileged", NULL); + assert_false(isc_task_getprivilege(task1)); + isc_task_setprivilege(task1, true); + assert_true(isc_task_getprivilege(task1)); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task2, "normal", NULL); + assert_false(isc_task_getprivilege(task2)); + + /* First event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &a, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), -1); + isc_task_send(task1, &event); + + /* Second event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, + set_and_drop, &b, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), -1); + isc_task_send(task2, &event); + + /* Third event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &c, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&c), -1); + isc_task_send(task1, &event); + + /* Fourth event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &d, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&d), -1); + isc_task_send(task1, &event); + + /* Fifth event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, + set_and_drop, &e, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&e), -1); + isc_task_send(task2, &event); + + isc_nm_resume(netmgr); + + /* We're waiting for all variables to be set. */ + while ((atomic_load(&a) == -1 || atomic_load(&b) == -1 || + atomic_load(&c) == -1 || atomic_load(&d) == -1 || + atomic_load(&e) == -1) && + i++ < 5000) + { + isc_test_nap(1000); + } + + /* + * We need to check that all privilege mode events were fired + * in privileged mode, and non privileged in non-privileged. + */ + assert_true(atomic_load(&a) <= 3); + assert_true(atomic_load(&c) <= 3); + assert_true(atomic_load(&d) <= 3); + + /* ...and neither of the non-privileged tasks did... */ + assert_true(atomic_load(&b) > 3); + assert_true(atomic_load(&e) > 3); + + /* ...but all five of them did run. */ + assert_int_equal(atomic_load(&counter), 6); + + isc_task_destroy(&task1); + assert_null(task1); + isc_task_destroy(&task2); + assert_null(task2); +} + +/* + * Basic task functions: + */ +static void +basic_cb(isc_task_t *task, isc_event_t *event) { + int i, j; + + UNUSED(task); + + j = 0; + for (i = 0; i < 1000000; i++) { + j += 100; + } + + UNUSED(j); + + if (verbose) { + print_message("# task %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static void +basic_shutdown(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (verbose) { + print_message("# shutdown %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static void +basic_tick(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (verbose) { + print_message("# %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static char one[] = "1"; +static char two[] = "2"; +static char three[] = "3"; +static char four[] = "4"; +static char tick[] = "tick"; +static char tock[] = "tock"; + +ISC_RUN_TEST_IMPL(basic) { + isc_result_t result; + isc_task_t *task1 = NULL; + isc_task_t *task2 = NULL; + isc_task_t *task3 = NULL; + isc_task_t *task4 = NULL; + isc_event_t *event = NULL; + isc_timer_t *ti1 = NULL; + isc_timer_t *ti2 = NULL; + isc_time_t absolute; + isc_interval_t interval; + char *testarray[] = { one, one, one, one, one, one, one, one, + one, two, three, four, two, three, four, NULL }; + int i; + + UNUSED(state); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task3); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task4); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task1, basic_shutdown, one); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task2, basic_shutdown, two); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task3, basic_shutdown, three); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task4, basic_shutdown, four); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_settoepoch(&absolute); + isc_interval_set(&interval, 1, 0); + result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute, + &interval, task1, basic_tick, tick, &ti1); + assert_int_equal(result, ISC_R_SUCCESS); + + ti2 = NULL; + isc_time_settoepoch(&absolute); + isc_interval_set(&interval, 1, 0); + result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute, + &interval, task2, basic_tick, tock, &ti2); + assert_int_equal(result, ISC_R_SUCCESS); + + sleep(2); + + for (i = 0; testarray[i] != NULL; i++) { + /* + * Note: (void *)1 is used as a sender here, since some + * compilers don't like casting a function pointer to a + * (void *). + * + * In a real use, it is more likely the sender would be a + * structure (socket, timer, task, etc) but this is just a + * test program. + */ + event = isc_event_allocate(mctx, (void *)1, 1, basic_cb, + testarray[i], sizeof(*event)); + assert_non_null(event); + isc_task_send(task1, &event); + } + + (void)isc_task_purge(task3, NULL, 0, 0); + + isc_task_detach(&task1); + isc_task_detach(&task2); + isc_task_detach(&task3); + isc_task_detach(&task4); + + sleep(10); + isc_timer_destroy(&ti1); + isc_timer_destroy(&ti2); +} + +/* + * Exclusive mode test: + * When one task enters exclusive mode, all other active + * tasks complete first. + */ +static int +spin(int n) { + int i; + int r = 0; + for (i = 0; i < n; i++) { + r += i; + if (r > 1000000) { + r = 0; + } + } + return (r); +} + +static void +exclusive_cb(isc_task_t *task, isc_event_t *event) { + int taskno = *(int *)(event->ev_arg); + + if (verbose) { + print_message("# task enter %d\n", taskno); + } + + /* task chosen from the middle of the range */ + if (taskno == 6) { + isc_result_t result; + int i; + + result = isc_task_beginexclusive(task); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 10; i++) { + assert_int_equal(active[i], 0); + } + + isc_task_endexclusive(task); + atomic_store(&done, true); + } else { + active[taskno]++; + (void)spin(10000000); + active[taskno]--; + } + + if (verbose) { + print_message("# task exit %d\n", taskno); + } + + if (atomic_load(&done)) { + isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof(int)); + isc_event_free(&event); + atomic_fetch_sub(&counter, 1); + } else { + isc_task_send(task, &event); + } +} + +ISC_RUN_TEST_IMPL(task_exclusive) { + isc_task_t *tasks[10]; + isc_result_t result; + int i; + + UNUSED(state); + + atomic_init(&counter, 0); + + for (i = 0; i < 10; i++) { + isc_event_t *event = NULL; + int *v; + + tasks[i] = NULL; + + if (i == 6) { + /* task chosen from the middle of the range */ + result = isc_task_create_bound(taskmgr, 0, &tasks[i], + 0); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_taskmgr_setexcltask(taskmgr, tasks[6]); + } else { + result = isc_task_create(taskmgr, 0, &tasks[i]); + assert_int_equal(result, ISC_R_SUCCESS); + } + + v = isc_mem_get(mctx, sizeof *v); + assert_non_null(v); + + *v = i; + + event = isc_event_allocate(mctx, NULL, 1, exclusive_cb, v, + sizeof(*event)); + assert_non_null(event); + + isc_task_send(tasks[i], &event); + atomic_fetch_add(&counter, 1); + } + + for (i = 0; i < 10; i++) { + isc_task_detach(&tasks[i]); + } + + while (atomic_load(&counter) > 0) { + uv_sleep(1); + } +} + +/* + * Max tasks test: + * The task system can create and execute many tasks. Tests with 10000. + */ +static void +maxtask_shutdown(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (event->ev_arg != NULL) { + isc_task_destroy((isc_task_t **)&event->ev_arg); + } else { + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + } + + isc_event_free(&event); +} + +static void +maxtask_cb(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + + if (event->ev_arg != NULL) { + isc_task_t *newtask = NULL; + + event->ev_arg = (void *)(((uintptr_t)event->ev_arg) - 1); + + /* + * Create a new task and forward the message. + */ + result = isc_task_create(taskmgr, 0, &newtask); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(newtask, maxtask_shutdown, + (void *)task); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_send(newtask, &event); + } else if (task != NULL) { + isc_task_destroy(&task); + isc_event_free(&event); + } +} + +ISC_RUN_TEST_IMPL(manytasks) { + isc_event_t *event = NULL; + uintptr_t ntasks = 10000; + + UNUSED(state); + + if (verbose) { + print_message("# Testing with %lu tasks\n", + (unsigned long)ntasks); + } + + atomic_init(&done, false); + + event = isc_event_allocate(mctx, (void *)1, 1, maxtask_cb, + (void *)ntasks, sizeof(*event)); + assert_non_null(event); + + LOCK(&lock); + maxtask_cb(NULL, event); + while (!atomic_load(&done)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); +} + +/* + * Shutdown test: + * When isc_task_shutdown() is called, shutdown events are posted + * in LIFO order. + */ + +static int nevents = 0; +static int nsdevents = 0; +static int senders[4]; +atomic_bool ready, all_done; + +static void +sd_sde1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + assert_int_equal(nevents, 256); + assert_int_equal(nsdevents, 1); + ++nsdevents; + + if (verbose) { + print_message("# shutdown 1\n"); + } + + isc_event_free(&event); + + atomic_store(&all_done, true); +} + +static void +sd_sde2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + assert_int_equal(nevents, 256); + assert_int_equal(nsdevents, 0); + ++nsdevents; + + if (verbose) { + print_message("# shutdown 2\n"); + } + + isc_event_free(&event); +} + +static void +sd_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&ready)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + if (verbose) { + print_message("# event 1\n"); + } + + isc_event_free(&event); +} + +static void +sd_event2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + ++nevents; + + if (verbose) { + print_message("# event 2\n"); + } + + isc_event_free(&event); +} + +ISC_RUN_TEST_IMPL(task_shutdown) { + isc_result_t result; + isc_eventtype_t event_type; + isc_event_t *event = NULL; + isc_task_t *task = NULL; + int i; + + UNUSED(state); + + nevents = nsdevents = 0; + event_type = 3; + atomic_init(&ready, false); + atomic_init(&all_done, false); + + LOCK(&lock); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * This event causes the task to wait on cv. + */ + event = isc_event_allocate(mctx, &senders[1], event_type, sd_event1, + NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + + /* + * Now we fill up the task's event queue with some events. + */ + for (i = 0; i < 256; ++i) { + event = isc_event_allocate(mctx, &senders[1], event_type, + sd_event2, NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + } + + /* + * Now we register two shutdown events. + */ + result = isc_task_onshutdown(task, sd_sde1, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, sd_sde2, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_shutdown(task); + isc_task_detach(&task); + + /* + * Now we free the task by signaling cv. + */ + atomic_store(&ready, true); + SIGNAL(&cv); + UNLOCK(&lock); + + while (!atomic_load(&all_done)) { + isc_test_nap(1000); + } + + assert_int_equal(nsdevents, 2); +} + +/* + * Post-shutdown test: + * After isc_task_shutdown() has been called, any call to + * isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN. + */ +static void +psd_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + + while (!atomic_load(&done)) { + WAIT(&cv, &lock); + } + + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +psd_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + isc_event_free(&event); +} + +ISC_RUN_TEST_IMPL(post_shutdown) { + isc_result_t result; + isc_eventtype_t event_type; + isc_event_t *event; + isc_task_t *task; + + UNUSED(state); + + atomic_init(&done, false); + event_type = 4; + + isc_condition_init(&cv); + + LOCK(&lock); + + task = NULL; + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * This event causes the task to wait on cv. + */ + event = isc_event_allocate(mctx, &senders[1], event_type, psd_event1, + NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + + isc_task_shutdown(task); + + result = isc_task_onshutdown(task, psd_sde, NULL); + assert_int_equal(result, ISC_R_SHUTTINGDOWN); + + /* + * Release the task. + */ + atomic_store(&done, true); + + SIGNAL(&cv); + UNLOCK(&lock); + + isc_task_detach(&task); +} + +/* + * Helper for the purge tests below: + */ + +#define SENDERCNT 3 +#define TYPECNT 4 +#define TAGCNT 5 +#define NEVENTS (SENDERCNT * TYPECNT * TAGCNT) + +static bool testrange; +static void *purge_sender; +static isc_eventtype_t purge_type_first; +static isc_eventtype_t purge_type_last; +static void *purge_tag; +static int eventcnt; + +atomic_bool started; + +static void +pg_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&started)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +pg_event2(isc_task_t *task, isc_event_t *event) { + bool sender_match = false; + bool type_match = false; + bool tag_match = false; + + UNUSED(task); + + if ((purge_sender == NULL) || (purge_sender == event->ev_sender)) { + sender_match = true; + } + + if (testrange) { + if ((purge_type_first <= event->ev_type) && + (event->ev_type <= purge_type_last)) + { + type_match = true; + } + } else { + if (purge_type_first == event->ev_type) { + type_match = true; + } + } + + if ((purge_tag == NULL) || (purge_tag == event->ev_tag)) { + tag_match = true; + } + + if (sender_match && type_match && tag_match) { + if ((event->ev_attributes & ISC_EVENTATTR_NOPURGE) != 0) { + if (verbose) { + print_message("# event %p,%d,%p " + "matched but was not " + "purgeable\n", + event->ev_sender, + (int)event->ev_type, + event->ev_tag); + } + ++eventcnt; + } else if (verbose) { + print_message("# event %p,%d,%p not purged\n", + event->ev_sender, (int)event->ev_type, + event->ev_tag); + } + } else { + ++eventcnt; + } + + isc_event_free(&event); +} + +static void +pg_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +test_purge(int sender, int type, int tag, int exp_purged) { + isc_result_t result; + isc_task_t *task = NULL; + isc_event_t *eventtab[NEVENTS]; + isc_event_t *event = NULL; + isc_interval_t interval; + isc_time_t now; + int sender_cnt, type_cnt, tag_cnt, event_cnt, i; + int purged = 0; + + atomic_init(&started, false); + atomic_init(&done, false); + eventcnt = 0; + + isc_condition_init(&cv); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, pg_sde, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Block the task on cv. + */ + event = isc_event_allocate(mctx, (void *)1, 9999, pg_event1, NULL, + sizeof(*event)); + + assert_non_null(event); + isc_task_send(task, &event); + + /* + * Fill the task's queue with some messages with varying + * sender, type, tag, and purgeable attribute values. + */ + event_cnt = 0; + for (sender_cnt = 0; sender_cnt < SENDERCNT; ++sender_cnt) { + for (type_cnt = 0; type_cnt < TYPECNT; ++type_cnt) { + for (tag_cnt = 0; tag_cnt < TAGCNT; ++tag_cnt) { + eventtab[event_cnt] = isc_event_allocate( + mctx, &senders[sender + sender_cnt], + (isc_eventtype_t)(type + type_cnt), + pg_event2, NULL, sizeof(*event)); + + assert_non_null(eventtab[event_cnt]); + + eventtab[event_cnt]->ev_tag = + (void *)((uintptr_t)tag + tag_cnt); + + /* + * Mark events as non-purgeable if + * sender, type and tag are all + * odd-numbered. (There should be 4 + * of these out of 60 events total.) + */ + if (((sender_cnt % 2) != 0) && + ((type_cnt % 2) != 0) && + ((tag_cnt % 2) != 0)) + { + eventtab[event_cnt]->ev_attributes |= + ISC_EVENTATTR_NOPURGE; + } + ++event_cnt; + } + } + } + + for (i = 0; i < event_cnt; ++i) { + isc_task_send(task, &eventtab[i]); + } + + if (testrange) { + /* + * We're testing isc_task_purgerange. + */ + purged = isc_task_purgerange( + task, purge_sender, (isc_eventtype_t)purge_type_first, + (isc_eventtype_t)purge_type_last, purge_tag); + assert_int_equal(purged, exp_purged); + } else { + /* + * We're testing isc_task_purge. + */ + if (verbose) { + print_message("# purge events %p,%u,%p\n", purge_sender, + purge_type_first, purge_tag); + } + purged = isc_task_purge(task, purge_sender, + (isc_eventtype_t)purge_type_first, + purge_tag); + if (verbose) { + print_message("# purged %d expected %d\n", purged, + exp_purged); + } + + assert_int_equal(purged, exp_purged); + } + + /* + * Unblock the task, allowing event processing. + */ + LOCK(&lock); + atomic_store(&started, true); + SIGNAL(&cv); + + isc_task_shutdown(task); + + isc_interval_set(&interval, 5, 0); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&done)) { + result = isc_time_nowplusinterval(&now, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + WAITUNTIL(&cv, &lock, &now); + } + + UNLOCK(&lock); + + isc_task_detach(&task); + + assert_int_equal(eventcnt, event_cnt - exp_purged); +} + +/* + * Purge test: + * A call to isc_task_purge(task, sender, type, tag) purges all events of + * type 'type' and with tag 'tag' not marked as unpurgeable from sender + * from the task's " queue and returns the number of events purged. + */ +ISC_RUN_TEST_IMPL(purge) { + UNUSED(state); + + /* Try purging on a specific sender. */ + if (verbose) { + print_message("# testing purge on 2,4,8 expecting 1\n"); + } + purge_sender = &senders[2]; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 1); + + /* Try purging on all senders. */ + if (verbose) { + print_message("# testing purge on 0,4,8 expecting 3\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 3); + + /* Try purging on all senders, specified type, all tags. */ + if (verbose) { + print_message("# testing purge on 0,4,0 expecting 15\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = NULL; + testrange = false; + test_purge(1, 4, 7, 15); + + /* Try purging on a specified tag, no such type. */ + if (verbose) { + print_message("# testing purge on 0,99,8 expecting 0\n"); + } + purge_sender = NULL; + purge_type_first = 99; + purge_type_last = 99; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 0); + + /* Try purging on specified sender, type, all tags. */ + if (verbose) { + print_message("# testing purge on 3,5,0 expecting 5\n"); + } + purge_sender = &senders[3]; + purge_type_first = 5; + purge_type_last = 5; + purge_tag = NULL; + testrange = false; + test_purge(1, 4, 7, 5); +} + +/* + * Purge range test: + * A call to isc_event_purgerange(task, sender, first, last, tag) purges + * all events not marked unpurgeable from sender 'sender' and of type within + * the range 'first' to 'last' inclusive from the task's event queue and + * returns the number of tasks purged. + */ + +ISC_RUN_TEST_IMPL(purgerange) { + UNUSED(state); + + /* Now let's try some ranges. */ + /* testing purgerange on 2,4-5,8 expecting 1 */ + purge_sender = &senders[2]; + purge_type_first = 4; + purge_type_last = 5; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 1); + + /* Try purging on all senders. */ + if (verbose) { + print_message("# testing purge on 0,4-5,8 expecting 5\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 5; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 5); + + /* Try purging on all senders, specified type, all tags. */ + if (verbose) { + print_message("# testing purge on 0,5-6,0 expecting 28\n"); + } + purge_sender = NULL; + purge_type_first = 5; + purge_type_last = 6; + purge_tag = NULL; + testrange = true; + test_purge(1, 4, 7, 28); + + /* Try purging on a specified tag, no such type. */ + if (verbose) { + print_message("# testing purge on 0,99-101,8 expecting 0\n"); + } + purge_sender = NULL; + purge_type_first = 99; + purge_type_last = 101; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 0); + + /* Try purging on specified sender, type, all tags. */ + if (verbose) { + print_message("# testing purge on 3,5-6,0 expecting 10\n"); + } + purge_sender = &senders[3]; + purge_type_first = 5; + purge_type_last = 6; + purge_tag = NULL; + testrange = true; + test_purge(1, 4, 7, 10); +} + +/* + * Helpers for purge event tests + */ +static void +pge_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&started)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +pge_event2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + ++eventcnt; + isc_event_free(&event); +} + +static void +pge_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +try_purgeevent(bool purgeable) { + isc_result_t result; + isc_task_t *task = NULL; + bool purged; + isc_event_t *event1 = NULL; + isc_event_t *event2 = NULL; + isc_event_t *event2_clone = NULL; + isc_time_t now; + isc_interval_t interval; + + atomic_init(&started, false); + atomic_init(&done, false); + eventcnt = 0; + + isc_condition_init(&cv); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, pge_sde, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Block the task on cv. + */ + event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, + pge_event1, NULL, sizeof(*event1)); + assert_non_null(event1); + isc_task_send(task, &event1); + + event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, + pge_event2, NULL, sizeof(*event2)); + assert_non_null(event2); + + event2_clone = event2; + + if (purgeable) { + event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE; + } else { + event2->ev_attributes |= ISC_EVENTATTR_NOPURGE; + } + + isc_task_send(task, &event2); + + purged = isc_task_purgeevent(task, event2_clone); + assert_int_equal(purgeable, purged); + + /* + * Unblock the task, allowing event processing. + */ + LOCK(&lock); + atomic_store(&started, true); + SIGNAL(&cv); + + isc_task_shutdown(task); + + isc_interval_set(&interval, 5, 0); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&done)) { + result = isc_time_nowplusinterval(&now, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + WAITUNTIL(&cv, &lock, &now); + } + UNLOCK(&lock); + + isc_task_detach(&task); + + assert_int_equal(eventcnt, (purgeable ? 0 : 1)); +} + +/* + * Purge event test: + * When the event is marked as purgeable, a call to + * isc_task_purgeevent(task, event) purges the event 'event' from the + * task's queue and returns true. + */ + +ISC_RUN_TEST_IMPL(purgeevent) { + UNUSED(state); + + try_purgeevent(true); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(manytasks, _setup4, _teardown) +ISC_TEST_ENTRY_CUSTOM(all_events, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(basic, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(create_task, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(post_shutdown, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(privilege_drop, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(privileged_events, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(purge, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(purgeevent, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(task_shutdown, _setup4, _teardown) +ISC_TEST_ENTRY_CUSTOM(task_exclusive, _setup4, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/taskpool_test.c b/tests/isc/taskpool_test.c new file mode 100644 index 0000000..a92e0ad --- /dev/null +++ b/tests/isc/taskpool_test.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include + +#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K') +#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC) + +/* Create a taskpool */ +ISC_RUN_TEST_IMPL(create_pool) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 8, 2, false, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 8); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +/* Resize a taskpool */ +ISC_RUN_TEST_IMPL(expand_pool) { + isc_result_t result; + isc_taskpool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 10, 2, false, &pool1); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool1), 10); + + /* resizing to a smaller size should have no effect */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 5, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to the same size should have no effect */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 10, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to larger size should make a new pool */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 20, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 20); + assert_ptr_not_equal(pool2, hold); + assert_null(pool1); + + isc_taskpool_destroy(&pool2); + assert_null(pool2); +} + +/* Get tasks */ +ISC_RUN_TEST_IMPL(get_tasks) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 2, 2, false, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 2); + + /* two tasks in pool; make sure we can access them more than twice */ + isc_taskpool_gettask(pool, &task1); + assert_true(VALID_TASK(task1)); + + isc_taskpool_gettask(pool, &task2); + assert_true(VALID_TASK(task2)); + + isc_taskpool_gettask(pool, &task3); + assert_true(VALID_TASK(task3)); + + isc_task_destroy(&task1); + isc_task_destroy(&task2); + isc_task_destroy(&task3); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +/* Set privileges */ +ISC_RUN_TEST_IMPL(set_privilege) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 2, 2, true, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 2); + + isc_taskpool_gettask(pool, &task1); + isc_taskpool_gettask(pool, &task2); + isc_taskpool_gettask(pool, &task3); + + assert_true(VALID_TASK(task1)); + assert_true(VALID_TASK(task2)); + assert_true(VALID_TASK(task3)); + + assert_true(isc_task_getprivilege(task1)); + assert_true(isc_task_getprivilege(task2)); + assert_true(isc_task_getprivilege(task3)); + + isc_task_destroy(&task1); + isc_task_destroy(&task2); + isc_task_destroy(&task3); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(create_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(expand_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(get_tasks, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(set_privilege, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/testdata/file/keep b/tests/isc/testdata/file/keep new file mode 100644 index 0000000..e69de29 diff --git a/tests/isc/time_test.c b/tests/isc/time_test.c new file mode 100644 index 0000000..6b0f329 --- /dev/null +++ b/tests/isc/time_test.c @@ -0,0 +1,418 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include "time.c" + +#include + +#define MAX_NS (NS_PER_SEC - 1) + +struct time_vectors { + isc_time_t a; + isc_interval_t b; + isc_time_t r; + isc_result_t result; +}; + +const struct time_vectors vectors_add[8] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS }, + { { 0, MAX_NS }, { 0, MAX_NS }, { 1, MAX_NS - 1 }, ISC_R_SUCCESS }, + { { 0, NS_PER_SEC / 2 }, + { 0, NS_PER_SEC / 2 }, + { 1, 0 }, + ISC_R_SUCCESS }, + { { UINT_MAX, MAX_NS }, { 0, 0 }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS }, + { { UINT_MAX, 0 }, { 0, MAX_NS }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS }, + { { UINT_MAX, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE }, + { { UINT_MAX, MAX_NS }, { 0, 1 }, { 0, 0 }, ISC_R_RANGE }, + { { UINT_MAX / 2 + 1, NS_PER_SEC / 2 }, + { UINT_MAX / 2, NS_PER_SEC / 2 }, + { 0, 0 }, + ISC_R_RANGE }, +}; + +const struct time_vectors vectors_sub[7] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS }, + { { 1, 0 }, { 0, MAX_NS }, { 0, 1 }, ISC_R_SUCCESS }, + { { 1, NS_PER_SEC / 2 }, + { 0, MAX_NS }, + { 0, NS_PER_SEC / 2 + 1 }, + ISC_R_SUCCESS }, + { { UINT_MAX, MAX_NS }, { UINT_MAX, 0 }, { 0, MAX_NS }, ISC_R_SUCCESS }, + { { 0, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE }, + { { 0, 0 }, { 0, MAX_NS }, { 0, 0 }, ISC_R_RANGE }, +}; + +ISC_RUN_TEST_IMPL(isc_time_add_test) { + UNUSED(state); + + for (size_t i = 0; i < ARRAY_SIZE(vectors_add); i++) { + isc_time_t r = { UINT_MAX, UINT_MAX }; + isc_result_t result = isc_time_add(&(vectors_add[i].a), + &(vectors_add[i].b), &r); + assert_int_equal(result, vectors_add[i].result); + if (result != ISC_R_SUCCESS) { + continue; + } + + assert_int_equal(r.seconds, vectors_add[i].r.seconds); + assert_int_equal(r.nanoseconds, vectors_add[i].r.nanoseconds); + } + + expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, MAX_NS + 1 }, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 }, + &(isc_time_t){ 0, 0 })); + + expect_assert_failure((void)isc_time_add((isc_time_t *)NULL, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, 0 }, + (isc_interval_t *)NULL, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL)); +} + +ISC_RUN_TEST_IMPL(isc_time_sub_test) { + UNUSED(state); + + for (size_t i = 0; i < ARRAY_SIZE(vectors_sub); i++) { + isc_time_t r = { UINT_MAX, UINT_MAX }; + isc_result_t result = isc_time_subtract( + &(vectors_sub[i].a), &(vectors_sub[i].b), &r); + assert_int_equal(result, vectors_sub[i].result); + if (result != ISC_R_SUCCESS) { + continue; + } + assert_int_equal(r.seconds, vectors_sub[i].r.seconds); + assert_int_equal(r.nanoseconds, vectors_sub[i].r.nanoseconds); + } + + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, MAX_NS + 1 }, &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 }, + &(isc_time_t){ 0, 0 })); + + expect_assert_failure((void)isc_time_subtract((isc_time_t *)NULL, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract(&(isc_time_t){ 0, 0 }, + (isc_interval_t *)NULL, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL)); +} + +/* parse http time stamp */ + +ISC_RUN_TEST_IMPL(isc_time_parsehttptimestamp_test) { + isc_result_t result; + isc_time_t t, x; + char buf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_formathttptimestamp(&t, buf, sizeof(buf)); + result = isc_time_parsehttptimestamp(buf, &x); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_time_seconds(&t), isc_time_seconds(&x)); +} + +/* print UTC in ISO8601 */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 20); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40Z"); +} + +/* print UTC in ISO8601 with milliseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601ms_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.sssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 24); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + assert_int_equal(buf[23], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00.000Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40.123Z"); +} + +/* print UTC in ISO8601 with microseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601us_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now_hires(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 27); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + assert_int_equal(buf[26], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00.000000Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40.123456Z"); +} + +/* print local time in ISO8601 */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601L_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 19); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40"); +} + +/* print local time in ISO8601 with milliseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lms_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.sss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 23); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00.000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40.123"); +} + +/* print local time in ISO8601 with microseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lus_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now_hires(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 26); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00.000000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40.123456"); +} + +/* print UTC time as yyyymmddhhmmsssss */ + +ISC_RUN_TEST_IMPL(isc_time_formatshorttimestamp_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyymmddhhmmsssss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 17); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_string_equal(buf, "19700101000000000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_string_equal(buf, "20151213094640123"); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_time_add_test) +ISC_TEST_ENTRY(isc_time_sub_test) +ISC_TEST_ENTRY(isc_time_parsehttptimestamp_test) +ISC_TEST_ENTRY(isc_time_formatISO8601_test) +ISC_TEST_ENTRY(isc_time_formatISO8601ms_test) +ISC_TEST_ENTRY(isc_time_formatISO8601us_test) +ISC_TEST_ENTRY(isc_time_formatISO8601L_test) +ISC_TEST_ENTRY(isc_time_formatISO8601Lms_test) +ISC_TEST_ENTRY(isc_time_formatISO8601Lus_test) +ISC_TEST_ENTRY(isc_time_formatshorttimestamp_test) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/timer_test.c b/tests/isc/timer_test.c new file mode 100644 index 0000000..644018a --- /dev/null +++ b/tests/isc/timer_test.c @@ -0,0 +1,599 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netmgr/uv-compat.h" +#include "timer.c" + +#include + +/* Set to true (or use -v option) for verbose output */ +static bool verbose = false; + +#define FUDGE_SECONDS 0 /* in absence of clock_getres() */ +#define FUDGE_NANOSECONDS 500000000 /* in absence of clock_getres() */ + +static isc_timer_t *timer = NULL; +static isc_condition_t cv; +static isc_mutex_t mx; +static isc_time_t endtime; +static isc_mutex_t lasttime_mx; +static isc_time_t lasttime; +static int seconds; +static int nanoseconds; +static atomic_int_fast32_t eventcnt; +static atomic_uint_fast32_t errcnt; +static int nevents; + +static int +_setup(void **state) { + atomic_init(&errcnt, ISC_R_SUCCESS); + + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + + return (0); +} + +static void +test_shutdown(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + + UNUSED(task); + + /* + * Signal shutdown processing complete. + */ + result = isc_mutex_lock(&mx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_condition_signal(&cv); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_mutex_unlock(&mx); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_event_free(&event); +} + +static void +setup_test(isc_timertype_t timertype, isc_time_t *expires, + isc_interval_t *interval, + void (*action)(isc_task_t *, isc_event_t *)) { + isc_result_t result; + isc_task_t *task = NULL; + isc_time_settoepoch(&endtime); + atomic_init(&eventcnt, 0); + + isc_mutex_init(&mx); + isc_mutex_init(&lasttime_mx); + + isc_condition_init(&cv); + + atomic_store(&errcnt, ISC_R_SUCCESS); + + LOCK(&mx); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, test_shutdown, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_mutex_lock(&lasttime_mx); + result = isc_time_now(&lasttime); + isc_mutex_unlock(&lasttime_mx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_timer_create(timermgr, timertype, expires, interval, task, + action, (void *)timertype, &timer); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Wait for shutdown processing to complete. + */ + while (atomic_load(&eventcnt) != nevents) { + result = isc_condition_wait(&cv, &mx); + assert_int_equal(result, ISC_R_SUCCESS); + } + + UNLOCK(&mx); + + assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS); + + isc_task_detach(&task); + isc_mutex_destroy(&mx); + isc_mutex_destroy(&lasttime_mx); + (void)isc_condition_destroy(&cv); +} + +static void +set_global_error(isc_result_t result) { + (void)atomic_compare_exchange_strong( + &errcnt, &(uint_fast32_t){ ISC_R_SUCCESS }, result); +} + +static void +subthread_assert_true(bool expected, const char *file, unsigned int line) { + if (!expected) { + printf("# %s:%u subthread_assert_true\n", file, line); + set_global_error(ISC_R_UNEXPECTED); + } +} +#define subthread_assert_true(expected) \ + subthread_assert_true(expected, __FILE__, __LINE__) + +static void +subthread_assert_int_equal(int observed, int expected, const char *file, + unsigned int line) { + if (observed != expected) { + printf("# %s:%u subthread_assert_int_equal(%d != %d)\n", file, + line, observed, expected); + set_global_error(ISC_R_UNEXPECTED); + } +} +#define subthread_assert_int_equal(observed, expected) \ + subthread_assert_int_equal(observed, expected, __FILE__, __LINE__) + +static void +subthread_assert_result_equal(isc_result_t result, isc_result_t expected, + const char *file, unsigned int line) { + if (result != expected) { + printf("# %s:%u subthread_assert_result_equal(%u != %u)\n", + file, line, (unsigned int)result, + (unsigned int)expected); + set_global_error(result); + } +} +#define subthread_assert_result_equal(observed, expected) \ + subthread_assert_result_equal(observed, expected, __FILE__, __LINE__) + +static void +ticktock(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_interval_t interval; + isc_eventtype_t expected_event_type; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + expected_event_type = ISC_TIMEREVENT_LIFE; + if ((uintptr_t)event->ev_arg == isc_timertype_ticker) { + expected_event_type = ISC_TIMEREVENT_TICK; + } + + if (event->ev_type != expected_event_type) { + print_error("# expected event type %u, got %u\n", + expected_event_type, event->ev_type); + } + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_event_free(&event); + + if (atomic_load(&eventcnt) == nevents) { + result = isc_time_now(&endtime); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + isc_timer_destroy(&timer); + isc_task_shutdown(task); + } +} + +/* + * Individual unit tests + */ + +/* timer type ticker */ +ISC_RUN_TEST_IMPL(ticker) { + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 12; + seconds = 0; + nanoseconds = 500000000; + + isc_interval_set(&interval, seconds, nanoseconds); + isc_time_settoepoch(&expires); + + setup_test(isc_timertype_ticker, &expires, &interval, ticktock); +} + +/* timer type once reaches lifetime */ +ISC_RUN_TEST_IMPL(once_life) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 1; + seconds = 1; + nanoseconds = 100000000; + + isc_interval_set(&interval, seconds, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + + setup_test(isc_timertype_once, &expires, &interval, ticktock); +} + +static void +test_idle(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_interval_t interval; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_IDLE); + + isc_event_free(&event); + + isc_timer_destroy(&timer); + isc_task_shutdown(task); +} + +/* timer type once idles out */ +ISC_RUN_TEST_IMPL(once_idle) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 1; + seconds = 1; + nanoseconds = 200000000; + + isc_interval_set(&interval, seconds + 1, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + + setup_test(isc_timertype_once, &expires, &interval, test_idle); +} + +/* timer reset */ +static void +test_reset(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_time_t expires; + isc_interval_t interval; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + /* + * Check expired time. + */ + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + + int _eventcnt = atomic_load(&eventcnt); + + if (_eventcnt < 3) { + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_TICK); + + if (_eventcnt == 2) { + isc_interval_set(&interval, seconds, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + result = isc_timer_reset(timer, isc_timertype_once, + &expires, &interval, false); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + } + + isc_event_free(&event); + } else { + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_LIFE); + + isc_event_free(&event); + isc_timer_destroy(&timer); + isc_task_shutdown(task); + } +} + +ISC_RUN_TEST_IMPL(reset) { + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 3; + seconds = 0; + nanoseconds = 750000000; + + isc_interval_set(&interval, seconds, nanoseconds); + isc_time_settoepoch(&expires); + + setup_test(isc_timertype_ticker, &expires, &interval, test_reset); +} + +static atomic_bool startflag; +static atomic_bool shutdownflag; +static isc_timer_t *tickertimer = NULL; +static isc_timer_t *oncetimer = NULL; +static isc_task_t *task1 = NULL; +static isc_task_t *task2 = NULL; + +/* + * task1 blocks on mx while events accumulate + * in its queue, until signaled by task2. + */ + +static void +tick_event(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(task); + + if (!atomic_load(&startflag)) { + if (verbose) { + print_message("# tick_event %d\n", -1); + } + isc_event_free(&event); + return; + } + + int tick = atomic_fetch_add(&eventcnt, 1); + if (verbose) { + print_message("# tick_event %d\n", tick); + } + + /* + * On the first tick, purge all remaining tick events + * and then shut down the task. + */ + if (tick == 0) { + isc_time_settoepoch(&expires); + isc_interval_set(&interval, seconds, 0); + result = isc_timer_reset(tickertimer, isc_timertype_ticker, + &expires, &interval, true); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_task_shutdown(task); + } + + isc_event_free(&event); +} + +static void +once_event(isc_task_t *task, isc_event_t *event) { + if (verbose) { + print_message("# once_event\n"); + } + + /* + * Allow task1 to start processing events. + */ + atomic_store(&startflag, true); + + isc_event_free(&event); + isc_task_shutdown(task); +} + +static void +shutdown_purge(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + UNUSED(event); + + if (verbose) { + print_message("# shutdown_event\n"); + } + + /* + * Signal shutdown processing complete. + */ + atomic_store(&shutdownflag, 1); + + isc_event_free(&event); +} + +/* timer events purged */ +ISC_RUN_TEST_IMPL(purge) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + atomic_init(&startflag, 0); + atomic_init(&shutdownflag, 0); + atomic_init(&eventcnt, 0); + seconds = 1; + nanoseconds = 0; + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task1, shutdown_purge, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_settoepoch(&expires); + isc_interval_set(&interval, seconds, 0); + + tickertimer = NULL; + result = isc_timer_create(timermgr, isc_timertype_ticker, &expires, + &interval, task1, tick_event, NULL, + &tickertimer); + assert_int_equal(result, ISC_R_SUCCESS); + + oncetimer = NULL; + + isc_interval_set(&interval, (seconds * 2) + 1, 0); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + result = isc_timer_create(timermgr, isc_timertype_once, &expires, + &interval, task2, once_event, NULL, + &oncetimer); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&shutdownflag)) { + uv_sleep(1); + } + + assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS); + + assert_int_equal(atomic_load(&eventcnt), 1); + + isc_timer_destroy(&tickertimer); + isc_timer_destroy(&oncetimer); + isc_task_destroy(&task1); + isc_task_destroy(&task2); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(ticker, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(once_life, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(once_idle, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(reset, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(purge, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/uv_wrap.h b/tests/isc/uv_wrap.h new file mode 100644 index 0000000..5c557b8 --- /dev/null +++ b/tests/isc/uv_wrap.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#if HAVE_CMOCKA +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define UNIT_TESTING +#include + +#include "../netmgr/uv-compat.h" + +/* uv_udp_t */ + +int +__wrap_uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock); +int +__wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, + unsigned int flags); +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr); +int +__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name, + int *namelen); +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ +int +__wrap_uv_udp_getsockname(const uv_udp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_udp_send(uv_udp_send_t *req, uv_udp_t *handle, const uv_buf_t bufs[], + unsigned int nbufs, const struct sockaddr *addr, + uv_udp_send_cb send_cb); +int +__wrap_uv_udp_recv_start(uv_udp_t *handle, uv_alloc_cb alloc_cb, + uv_udp_recv_cb recv_cb); +int +__wrap_uv_udp_recv_stop(uv_udp_t *handle); + +/* uv_tcp_t */ +int +__wrap_uv_tcp_open(uv_tcp_t *handle, uv_os_sock_t sock); +int +__wrap_uv_tcp_bind(uv_tcp_t *handle, const struct sockaddr *addr, + unsigned int flags); +int +__wrap_uv_tcp_getsockname(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_tcp_getpeername(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_tcp_connect(uv_connect_t *req, uv_tcp_t *handle, + const struct sockaddr *addr, uv_connect_cb cb); + +/* uv_stream_t */ +int +__wrap_uv_listen(uv_stream_t *stream, int backlog, uv_connection_cb cb); +int +__wrap_uv_accept(uv_stream_t *server, uv_stream_t *client); + +/* uv_handle_t */ +int +__wrap_uv_send_buffer_size(uv_handle_t *handle, int *value); +int +__wrap_uv_recv_buffer_size(uv_handle_t *handle, int *value); +int +__wrap_uv_fileno(const uv_handle_t *handle, uv_os_fd_t *fd); + +/* uv_timer_t */ +/* FIXME */ +/* + * uv_timer_init + * uv_timer_start + */ + +static atomic_int __state_uv_udp_open = 0; + +int +__wrap_uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock) { + if (atomic_load(&__state_uv_udp_open) == 0) { + return (uv_udp_open(handle, sock)); + } + return (atomic_load(&__state_uv_udp_open)); +} + +static atomic_int __state_uv_udp_bind = 0; + +int +__wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, + unsigned int flags) { + if (atomic_load(&__state_uv_udp_bind) == 0) { + return (uv_udp_bind(handle, addr, flags)); + } + return (atomic_load(&__state_uv_udp_bind)); +} + +static atomic_int __state_uv_udp_connect __attribute__((unused)) = 0; + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) { + if (atomic_load(&__state_uv_udp_connect) == 0) { + return (uv_udp_connect(handle, addr)); + } + return (atomic_load(&__state_uv_udp_connect)); +} +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ + +static atomic_int __state_uv_udp_getpeername __attribute__((unused)) = 0; + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_udp_getpeername) == 0) { + return (uv_udp_getpeername(handle, name, namelen)); + } + return (atomic_load(&__state_uv_udp_getpeername)); +} +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ + +static atomic_int __state_uv_udp_getsockname = 0; +int +__wrap_uv_udp_getsockname(const uv_udp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_udp_getsockname) == 0) { + return (uv_udp_getsockname(handle, name, namelen)); + } + return (atomic_load(&__state_uv_udp_getsockname)); +} + +static atomic_int __state_uv_udp_send = 0; +int +__wrap_uv_udp_send(uv_udp_send_t *req, uv_udp_t *handle, const uv_buf_t bufs[], + unsigned int nbufs, const struct sockaddr *addr, + uv_udp_send_cb send_cb) { + if (atomic_load(&__state_uv_udp_send) == 0) { + return (uv_udp_send(req, handle, bufs, nbufs, addr, send_cb)); + } + return (atomic_load(&__state_uv_udp_send)); +} + +static atomic_int __state_uv_udp_recv_start = 0; +int +__wrap_uv_udp_recv_start(uv_udp_t *handle, uv_alloc_cb alloc_cb, + uv_udp_recv_cb recv_cb) { + if (atomic_load(&__state_uv_udp_recv_start) == 0) { + return (uv_udp_recv_start(handle, alloc_cb, recv_cb)); + } + return (atomic_load(&__state_uv_udp_recv_start)); +} + +static atomic_int __state_uv_udp_recv_stop = 0; +int +__wrap_uv_udp_recv_stop(uv_udp_t *handle) { + if (atomic_load(&__state_uv_udp_recv_stop) == 0) { + return (uv_udp_recv_stop(handle)); + } + return (atomic_load(&__state_uv_udp_recv_stop)); +} + +static atomic_int __state_uv_tcp_open = 0; +int +__wrap_uv_tcp_open(uv_tcp_t *handle, uv_os_sock_t sock) { + if (atomic_load(&__state_uv_tcp_open) == 0) { + return (uv_tcp_open(handle, sock)); + } + return (atomic_load(&__state_uv_tcp_open)); +} + +static atomic_int __state_uv_tcp_bind = 0; +int +__wrap_uv_tcp_bind(uv_tcp_t *handle, const struct sockaddr *addr, + unsigned int flags) { + if (atomic_load(&__state_uv_tcp_bind) == 0) { + return (uv_tcp_bind(handle, addr, flags)); + } + return (atomic_load(&__state_uv_tcp_bind)); +} + +static atomic_int __state_uv_tcp_getsockname = 0; +int +__wrap_uv_tcp_getsockname(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_tcp_getsockname) == 0) { + return (uv_tcp_getsockname(handle, name, namelen)); + } + return (atomic_load(&__state_uv_tcp_getsockname)); +} + +static atomic_int __state_uv_tcp_getpeername = 0; +int +__wrap_uv_tcp_getpeername(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_tcp_getpeername) == 0) { + return (uv_tcp_getpeername(handle, name, namelen)); + } + return (atomic_load(&__state_uv_tcp_getpeername)); +} + +static atomic_int __state_uv_tcp_connect = 0; +int +__wrap_uv_tcp_connect(uv_connect_t *req, uv_tcp_t *handle, + const struct sockaddr *addr, uv_connect_cb cb) { + if (atomic_load(&__state_uv_tcp_connect) == 0) { + return (uv_tcp_connect(req, handle, addr, cb)); + } + return (atomic_load(&__state_uv_tcp_connect)); +} + +static atomic_int __state_uv_listen = 0; +int +__wrap_uv_listen(uv_stream_t *stream, int backlog, uv_connection_cb cb) { + if (atomic_load(&__state_uv_listen) == 0) { + return (uv_listen(stream, backlog, cb)); + } + return (atomic_load(&__state_uv_listen)); +} + +static atomic_int __state_uv_accept = 0; +int +__wrap_uv_accept(uv_stream_t *server, uv_stream_t *client) { + if (atomic_load(&__state_uv_accept) == 0) { + return (uv_accept(server, client)); + } + return (atomic_load(&__state_uv_accept)); +} + +static atomic_int __state_uv_send_buffer_size = 0; +int +__wrap_uv_send_buffer_size(uv_handle_t *handle, int *value) { + if (atomic_load(&__state_uv_send_buffer_size) == 0) { + return (uv_send_buffer_size(handle, value)); + } + return (atomic_load(&__state_uv_send_buffer_size)); +} + +static atomic_int __state_uv_recv_buffer_size = 0; +int +__wrap_uv_recv_buffer_size(uv_handle_t *handle, int *value) { + if (atomic_load(&__state_uv_recv_buffer_size) == 0) { + return (uv_recv_buffer_size(handle, value)); + } + return (atomic_load(&__state_uv_recv_buffer_size)); +} + +static atomic_int __state_uv_fileno = 0; +int +__wrap_uv_fileno(const uv_handle_t *handle, uv_os_fd_t *fd) { + if (atomic_load(&__state_uv_fileno) == 0) { + return (uv_fileno(handle, fd)); + } + return (atomic_load(&__state_uv_fileno)); +} + +#define uv_udp_open(...) __wrap_uv_udp_open(__VA_ARGS__) +#define uv_udp_bind(...) __wrap_uv_udp_bind(__VA_ARGS__) +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +#define uv_udp_connect(...) __wrap_uv_udp_connect(__VA_ARGS__) +#define uv_udp_getpeername(...) __wrap_uv_udp_getpeername(__VA_ARGS__) +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ +#define uv_udp_getsockname(...) __wrap_uv_udp_getsockname(__VA_ARGS__) +#define uv_udp_send(...) __wrap_uv_udp_send(__VA_ARGS__) +#define uv_udp_recv_start(...) __wrap_uv_udp_recv_start(__VA_ARGS__) +#define uv_udp_recv_stop(...) __wrap_uv_udp_recv_stop(__VA_ARGS__) + +#define uv_tcp_open(...) __wrap_uv_tcp_open(__VA_ARGS__) +#define uv_tcp_bind(...) __wrap_uv_tcp_bind(__VA_ARGS__) +#define uv_tcp_getsockname(...) __wrap_uv_tcp_getsockname(__VA_ARGS__) +#define uv_tcp_getpeername(...) __wrap_uv_tcp_getpeername(__VA_ARGS__) +#define uv_tcp_connect(...) __wrap_uv_tcp_connect(__VA_ARGS__) + +#define uv_listen(...) __wrap_uv_listen(__VA_ARGS__) +#define uv_accept(...) __wrap_uv_accept(__VA_ARGS__) + +#define uv_send_buffer_size(...) __wrap_uv_send_buffer_size(__VA_ARGS__) +#define uv_recv_buffer_size(...) __wrap_uv_recv_buffer_size(__VA_ARGS__) +#define uv_fileno(...) __wrap_uv_fileno(__VA_ARGS__) + +#define RESET_RETURN \ + { \ + atomic_store(&__state_uv_udp_open, 0); \ + atomic_store(&__state_uv_udp_bind, 0); \ + atomic_store(&__state_uv_udp_connect, 0); \ + atomic_store(&__state_uv_udp_getpeername, 0); \ + atomic_store(&__state_uv_udp_getsockname, 0); \ + atomic_store(&__state_uv_udp_send, 0); \ + atomic_store(&__state_uv_udp_recv_start, 0); \ + atomic_store(&__state_uv_udp_recv_stop, 0); \ + atomic_store(&__state_uv_tcp_open, 0); \ + atomic_store(&__state_uv_tcp_bind, 0); \ + atomic_store(&__state_uv_tcp_getpeername, 0); \ + atomic_store(&__state_uv_tcp_getsockname, 0); \ + atomic_store(&__state_uv_tcp_connect, 0); \ + atomic_store(&__state_uv_listen, 0); \ + atomic_store(&__state_uv_accept, 0); \ + atomic_store(&__state_uv_send_buffer_size, 0); \ + atomic_store(&__state_uv_recv_buffer_size, 0); \ + atomic_store(&__state_uv_fileno, 0); \ + } + +#define WILL_RETURN(func, value) atomic_store(&__state_##func, value) + +#endif /* HAVE_CMOCKA */ -- cgit v1.2.3