]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Merge branch 'clean-bin-tests-v9_9' into 'v9_9'
authorEvan Hunt <each@isc.org>
Sat, 10 Mar 2018 07:35:06 +0000 (23:35 -0800)
committerEvan Hunt <each@isc.org>
Sat, 10 Mar 2018 07:52:26 +0000 (23:52 -0800)
clean up bin/tests, convert unit tests to ATF

Closes #115

See merge request isc-projects/bind9!93

1  2 
bin/tests/optional/Makefile.in
lib/dns/tests/dnstest.c
lib/dns/tests/dnstest.h
lib/dns/tests/dst_test.c
lib/dns/tests/rbt_test.c
lib/dns/tests/resolver_test.c
lib/isc/tests/Kyuafile
lib/isc/tests/Makefile.in
lib/isc/tests/mem_test.c

index 0000000000000000000000000000000000000000,d8ac74a1615eacb7aa058396d3d9cb88ab935a7e..559568916acdc74d16639c851521c90f7bb06579
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,304 +1,304 @@@
 -CDEFINES =    @CRYPTO@ @USE_GSSAPI@
+ # Copyright (C) 2018  Internet Systems Consortium, Inc. ("ISC")
+ #
+ # Permission to use, copy, modify, and/or distribute this software for any
+ # purpose with or without fee is hereby granted, provided that the above
+ # copyright notice and this permission notice appear in all copies.
+ #
+ # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ # AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ # PERFORMANCE OF THIS SOFTWARE.
+ srcdir =      @srcdir@
+ VPATH =               @srcdir@
+ top_srcdir =  @top_srcdir@
+ @BIND9_MAKE_INCLUDES@
+ CINCLUDES =   ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
+               ${LWRES_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
 -ISCLIBS =     ../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
 -ISCNOSYMLIBS =        ../../../lib/isc/libisc-nosymtbl.@A@ @ISC_OPENSSL_LIBS@
++CDEFINES =    @USE_GSSAPI@
+ CWARNINGS =
+ BACKTRACECFLAGS = @BACKTRACECFLAGS@
+ DNSLIBS =     ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
++ISCLIBS =     ../../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@
++ISCNOSYMLIBS =        ../../../lib/isc/libisc-nosymtbl.@A@ @DNS_CRYPTO_LIBS@
+ ISCCFGLIBS =  ../../../lib/isccfg/libisccfg.@A@
+ LWRESDEPLIBS =        ../../../lib/lwres/liblwres.@A@
+ DNSDEPLIBS =  ../../../lib/dns/libdns.@A@
+ ISCDEPLIBS =  ../../../lib/isc/libisc.@A@
+ ISCDEPNOSYMLIBS = ../../../lib/isc/libisc-nosymtbl.@A@
+ ISCCFGDEPLIBS = ../../../lib/isccfg/libisccfg.@A@
+ LWRESLIBS =   ../../../lib/lwres/liblwres.@A@
+ LIBS =                @LIBS@
+ SUBDIRS =
+ # These programs are not built by default, but only when
+ # configured with --enable-developer or built explicitly with
+ # "make all_tests"
+ TARGETS =     @XTARGETS@
+ XTARGETS =    adb_test@EXEEXT@ \
+               byaddr_test@EXEEXT@ \
+               backtrace_test@EXEEXT@ \
+               backtrace_test_nosymtbl@EXEEXT@ \
+               byname_test@EXEEXT@ \
+               db_test@EXEEXT@ \
+               dst_test@EXEEXT@ \
+               entropy_test@EXEEXT@ \
+               entropy2_test@EXEEXT@ \
+               gsstest@EXEEXT@ \
+               gxba_test@EXEEXT@ \
+               gxbn_test@EXEEXT@ \
+               hash_test@EXEEXT@ \
+               fsaccess_test@EXEEXT@ \
+               inter_test@EXEEXT@ \
+               keyboard_test@EXEEXT@ \
+               lex_test@EXEEXT@ \
+               lfsr_test@EXEEXT@ \
+               log_test@EXEEXT@ \
+               lwres_test@EXEEXT@ \
+               lwresconf_test@EXEEXT@ \
+               master_test@EXEEXT@ \
+               mempool_test@EXEEXT@ \
+               name_test@EXEEXT@ \
+               nsecify@EXEEXT@ \
+               ratelimiter_test@EXEEXT@ \
+               rbt_test@EXEEXT@ \
+               rwlock_test@EXEEXT@ \
+               serial_test@EXEEXT@ \
+               shutdown_test@EXEEXT@ \
+               sig0_test@EXEEXT@ \
+               sock_test@EXEEXT@ \
+               sym_test@EXEEXT@ \
+               task_test@EXEEXT@ \
+               timer_test@EXEEXT@ \
+               zone_test@EXEEXT@
+ SRCS =                ${XSRCS}
+ XSRCS =               adb_test.c \
+               byaddr_test.c \
+               backtrace_test.c \
+               byname_test.c \
+               db_test.c \
+               dst_test.c \
+               entropy_test.c \
+               entropy2_test.c \
+               hash_test.c \
+               fsaccess_test.c \
+               gsstest.c \
+               gxba_test.c \
+               gxbn_test.c \
+               inter_test.c \
+               keyboard_test.c \
+               lex_test.c \
+               lfsr_test.c \
+               log_test.c \
+               lwres_test.c \
+               lwresconf_test.c \
+               master_test.c \
+               mempool_test.c \
+               name_test.c \
+               nsecify.c \
+               ratelimiter_test.c \
+               rbt_test.c \
+               rwlock_test.c \
+               serial_test.c \
+               shutdown_test.c \
+               sig0_test.c \
+               sock_test.c \
+               sym_test.c \
+               task_test.c \
+               timer_test.c \
+               zone_test.c
+ @BIND9_MAKE_RULES@
+ # disable optimization for backtrace test to get the expected result
+ BTTEST_CFLAGS =       ${BACKTRACECFLAGS} ${EXT_CFLAGS} ${ALL_CPPFLAGS} -g \
+               ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS}
+ all_tests: ${XTARGETS}
+ adb_test@EXEEXT@: adb_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ adb_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ backtrace_test_nosymtbl@EXEEXT@: ${srcdir}/backtrace_test.c ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} -o $@ \
+       ${srcdir}/backtrace_test.c ${ISCLIBS} ${LIBS}
+ backtrace_test@EXEEXT@: ${srcdir}/backtrace_test.c backtrace_test_nosymtbl@EXEEXT@
+       #first step: create a first symbol table
+       rm -f symtbl.c
+       if test X${MKSYMTBL_PROGRAM} != X; then \
+       ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \
+       backtrace_test_nosymtbl@EXEEXT@; else \
+       cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi
+       #second step: build a binary with the first symbol table
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \
+       -o $@0 ${srcdir}/backtrace_test.c symtbl.c \
+       ${ISCNOSYMLIBS} ${LIBS}
+       rm -f symtbl.c
+       #third step: create a second symbol table
+       if test X${MKSYMTBL_PROGRAM} != X; then \
+       ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl $@0; else \
+       cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi
+       #fourth step: build the final binary
+       rm -f $@0
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \
+       -o $@ ${srcdir}/backtrace_test.c symtbl.c ${ISCNOSYMLIBS} ${LIBS}
+       rm -f symtbl.c
+ nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \
+               ${ISCLIBS} ${LIBS}
+ lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \
+               ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+ lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \
+               ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+ gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \
+               ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+ gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \
+               ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+ sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \
+               ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ dst_test@EXEEXT@: dst_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+               -o $@ dst_test.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ gsstest@EXEEXT@: gsstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+               -o $@ gsstest.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+ clean distclean::
+       rm -f ${TARGETS} ${XTARGETS}
+       rm -f backtrace_test_symtbl.c
+ check: test
+ test:
+       @for dir in $(TESTDIRS) ;\
+       do \
+               ( cd $$dir; $(MAKE) test ) ;\
+       done
index 9aab2d1246d87491ae494124cd1e262d2b6ab61e,e753eb0e6239d5df5c2384eaa152e1417c442e15..83b7286e3ebc225a24e83bdc54f9177cc1450b45
@@@ -193,6 -191,6 +191,25 @@@ dns_test_end(void) 
                isc_mem_destroy(&mctx);
  }
  
++/*
++ * Create a view.
++ */
++isc_result_t
++dns_test_makeview(const char *name, dns_view_t **viewp) {
++      isc_result_t result;
++      dns_view_t *view = NULL;
++
++      CHECK(dns_view_create(mctx, dns_rdataclass_in, name, &view));
++      *viewp = view;
++
++      return (ISC_R_SUCCESS);
++
++ cleanup:
++      if (view != NULL)
++              dns_view_detach(&view);
++      return (result);
++}
++
  /*
   * Create a zone with origin 'name', return a pointer to the zone object in
   * 'zonep'.  If 'view' is set, add the zone to that view; otherwise, create
index 42d572a75decd924ad91acb0c7c396140abba74c,1ab9fa8eca0c54141ec5cc902c8444d54ca1fee0..223053b1cfefdf7d2239d2edc4753a7d1bd9bd30
@@@ -56,6 -56,6 +56,9 @@@ dns_test_begin(FILE *logfile, isc_boole
  void
  dns_test_end(void);
  
++isc_result_t
++dns_test_makeview(const char *name, dns_view_t **viewp);
++
  isc_result_t
  dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view,
                                  isc_boolean_t keepview);
index 0000000000000000000000000000000000000000,d75acb5c4cb28af67c432769fba84f6baf4a5d5c..de14904b7f738e8ac78ab2ab802a67246075642a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,268 +1,267 @@@
 -      result = dst_context_create3(key, mctx, DNS_LOGCATEGORY_GENERAL,
 -                                   ISC_FALSE, &ctx);
+ /*
+  * Copyright (C) 2018  Internet Systems Consortium, Inc. ("ISC")
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ /* ! \file */
+ #include <config.h>
+ #include <atf-c.h>
+ #include <unistd.h>
+ #include <isc/file.h>
+ #include <isc/util.h>
+ #include <isc/stdio.h>
+ #include <isc/string.h>
+ #include <dst/dst.h>
+ #include <dst/result.h>
+ #include "../dst_internal.h"
+ #include "dnstest.h"
+ ATF_TC(sig);
+ ATF_TC_HEAD(sig, tc) {
+       atf_tc_set_md_var(tc, "descr", "signature ineffability");
+ }
+ /*
+  * Read sig in file at path to buf.
+  */
+ static isc_result_t
+ sig_fromfile(const char *path, isc_buffer_t *buf) {
+       isc_result_t result;
+       size_t rval, len;
+       FILE *fp = NULL;
+       unsigned char val;
+       char *p, *data;
+       off_t size;
+       result = isc_stdio_open(path, "rb", &fp);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_file_getsizefd(fileno(fp), &size);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       data = isc_mem_get(mctx, (size + 1));
+       ATF_REQUIRE(data != NULL);
+       len = (size_t)size;
+       p = data;
+       while (len != 0U) {
+               result = isc_stdio_read(p, 1, len, fp, &rval);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               len -= rval;
+               p += rval;
+       }
+       isc_stdio_close(fp);
+       p = data;
+       len = size;
+       while (len > 0U) {
+               if ((*p == '\r') || (*p == '\n')) {
+                       ++p;
+                       --len;
+                       continue;
+               } else if (len < 2U)
+                      goto err;
+               if (('0' <= *p) && (*p <= '9')) {
+                       val = *p - '0';
+               } else if (('A' <= *p) && (*p <= 'F')) {
+                       val = *p - 'A' + 10;
+               } else {
+                       result = ISC_R_BADHEX;
+                       goto err;
+               }
+               ++p;
+               val <<= 4;
+               --len;
+               if (('0' <= *p) && (*p <= '9')) {
+                       val |= (*p - '0');
+               } else if (('A' <= *p) && (*p <= 'F')) {
+                       val |= (*p - 'A' + 10);
+               } else {
+                       result = ISC_R_BADHEX;
+                       goto err;
+               }
+               ++p;
+               --len;
+               isc_buffer_putuint8(buf, val);
+       }
+       result = ISC_R_SUCCESS;
+  err:
+       isc_mem_put(mctx, data, size + 1);
+       return (result);
+ }
+ static void
+ check_sig(const char *datapath, const char *sigpath, const char *keyname,
+         dns_keytag_t id, dns_secalg_t alg, int type, isc_boolean_t expect)
+ {
+       isc_result_t result;
+       size_t rval, len;
+       FILE *fp;
+       dst_key_t *key = NULL;
+       unsigned char sig[512];
+       unsigned char *p;
+       unsigned char *data;
+       off_t size;
+       isc_buffer_t b;
+       isc_buffer_t databuf, sigbuf;
+       isc_region_t datareg, sigreg;
+       dns_fixedname_t fname;
+       dns_name_t *name;
+       dst_context_t *ctx = NULL;
+       /*
+        * Read data from file in a form usable by dst_verify.
+        */
+       result = isc_stdio_open(datapath, "rb", &fp);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_file_getsizefd(fileno(fp), &size);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       data = isc_mem_get(mctx, (size + 1));
+       ATF_REQUIRE(data != NULL);
+       p = data;
+       len = (size_t)size;
+       do {
+               result = isc_stdio_read(p, 1, len, fp, &rval);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               len -= rval;
+               p += rval;
+       } while (len);
+       isc_stdio_close(fp);
+       /*
+        * Read key from file in a form usable by dst_verify.
+        */
+       dns_fixedname_init(&fname);
+       name = dns_fixedname_name(&fname);
+       isc_buffer_constinit(&b, keyname, strlen(keyname));
+       isc_buffer_add(&b, strlen(keyname));
+       result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = dst_key_fromfile(name, id, alg, type, "testdata/dst",
+                                 mctx, &key);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_buffer_init(&databuf, data, (unsigned int)size);
+       isc_buffer_add(&databuf, (unsigned int)size);
+       isc_buffer_usedregion(&databuf, &datareg);
+       memset(sig, 0, sizeof(sig));
+       isc_buffer_init(&sigbuf, sig, sizeof(sig));
+       /*
+        * Read precomputed signature from file in a form usable by dst_verify.
+        */
+       result = sig_fromfile(sigpath, &sigbuf);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /*
+        * Verify that the key signed the data.
+        */
+       isc_buffer_remainingregion(&sigbuf, &sigreg);
++      result = dst_context_create2(key, mctx, DNS_LOGCATEGORY_GENERAL, &ctx);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = dst_context_adddata(ctx, &datareg);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = dst_context_verify(ctx, &sigreg);
+       ATF_REQUIRE((expect && (result == ISC_R_SUCCESS)) ||
+                   (!expect && (result != ISC_R_SUCCESS)));
+       isc_mem_put(mctx, data, size + 1);
+       dst_context_destroy(&ctx);
+       dst_key_free(&key);
+       return;
+ }
+ ATF_TC_BODY(sig, tc) {
+       isc_result_t result;
+       UNUSED(tc);
+       result = dns_test_begin(NULL, ISC_FALSE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       struct {
+               const char *datapath;
+               const char *sigpath;
+               const char *keyname;
+               dns_keytag_t keyid;
+               dns_secalg_t alg;
+               isc_boolean_t expect;
+       } testcases[] = {
+               {
+                       "testdata/dst/test1.data",
+                       "testdata/dst/test1.dsasig",
+                       "test.", 23616, DST_ALG_DSA, ISC_TRUE
+               },
+               {
+                       "testdata/dst/test1.data",
+                       "testdata/dst/test1.rsasig",
+                       "test.", 54622, DST_ALG_RSAMD5, ISC_TRUE
+               },
+               {
+                       /* wrong sig */
+                       "testdata/dst/test1.data",
+                       "testdata/dst/test1.dsasig",
+                       "test.", 54622, DST_ALG_RSAMD5, ISC_FALSE
+               },
+               {
+                       /* wrong data */
+                       "testdata/dst/test2.data",
+                       "testdata/dst/test1.dsasig",
+                       "test.", 23616, DST_ALG_DSA, ISC_FALSE
+               },
+       };
+       unsigned int i;
+       for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) {
+               if (!dst_algorithm_supported(testcases[i].alg)) {
+                       continue;
+               }
+               check_sig(testcases[i].datapath,
+                         testcases[i].sigpath,
+                         testcases[i].keyname,
+                         testcases[i].keyid,
+                         testcases[i].alg,
+                         DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+                         testcases[i].expect);
+       }
+       dns_test_end();
+ }
+ /*
+  * Main
+  */
+ ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, sig);
+       return (atf_no_error());
+ }
index 0000000000000000000000000000000000000000,e3657935cd806125122f90b8e31911cc9508ae7b..3ea251bdcd803e4fd1891968cdbf452bf34cbe82
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1426 +1,1381 @@@
 -      isc_boolean_t tree_ok;
+ /*
+  * Copyright (C) 2018  Internet Systems Consortium, Inc. ("ISC")
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ /* ! \file */
+ #include <config.h>
+ #include <atf-c.h>
+ #include <isc/mem.h>
+ #include <isc/random.h>
+ #include <isc/string.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #ifdef HAVE_INTTYPES_H
+ #include <inttypes.h> /* uintptr_t */
+ #endif
+ #include <dns/rbt.h>
+ #include <dns/fixedname.h>
+ #include <dns/name.h>
+ #include <dns/result.h>
+ #include <dns/compress.h>
+ #include "dnstest.h"
+ #include <isc/app.h>
+ #include <isc/buffer.h>
+ #include <isc/entropy.h>
+ #include <isc/file.h>
+ #include <isc/hash.h>
+ #include <isc/mem.h>
+ #include <isc/os.h>
+ #include <isc/string.h>
+ #include <isc/socket.h>
+ #include <isc/stdio.h>
+ #include <isc/task.h>
+ #include <isc/thread.h>
+ #include <isc/timer.h>
+ #include <isc/util.h>
+ #include <isc/print.h>
+ #include <isc/time.h>
+ #include <dns/log.h>
+ #include <dns/name.h>
+ #include <dns/result.h>
+ #include <dst/dst.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <time.h>
+ typedef struct {
+       dns_rbt_t *rbt;
+       dns_rbt_t *rbt_distances;
+ } test_context_t;
+ /* The initial structure of domain tree will be as follows:
+  *
+  *           .
+  *           |
+  *           b
+  *         /   \
+  *        a    d.e.f
+  *            /  |   \
+  *           c   |    g.h
+  *               |     |
+  *              w.y    i
+  *            /  |  \   \
+  *           x   |   z   k
+  *               |   |
+  *               p   j
+  *             /   \
+  *            o     q
+  */
+ /* The full absolute names of the nodes in the tree (the tree also
+  * contains "." which is not included in this list).
+  */
+ static const char * const domain_names[] = {
+     "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
+     "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"
+ };
+ static const size_t domain_names_count = (sizeof(domain_names) /
+                                         sizeof(domain_names[0]));
+ /* These are set as the node data for the tree used in distances check
+  * (for the names in domain_names[] above).
+  */
+ static const int node_distances[] = {
+     3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
+ };
+ /*
+  * The domain order should be:
+  * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f,
+  * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
+  *           . (no data, can't be found)
+  *           |
+  *           b
+  *         /   \
+  *        a    d.e.f
+  *            /  |   \
+  *           c   |    g.h
+  *               |     |
+  *              w.y    i
+  *            /  |  \   \
+  *           x   |   z   k
+  *               |   |
+  *               p   j
+  *             /   \
+  *            o     q
+  */
+ static const char * const ordered_names[] = {
+     "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
+     "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
+     "g.h", "i.g.h", "k.g.h"};
+ static const size_t ordered_names_count = (sizeof(ordered_names) /
+                                          sizeof(*ordered_names));
+ static void
+ delete_data(void *data, void *arg) {
+       UNUSED(arg);
+       isc_mem_put(mctx, data, sizeof(size_t));
+ }
+ static test_context_t *
+ test_context_setup(void) {
+       test_context_t *ctx;
+       isc_result_t result;
+       size_t i;
+       ctx = isc_mem_get(mctx, sizeof(*ctx));
+       ATF_REQUIRE(ctx != NULL);
+       ctx->rbt = NULL;
+       result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ctx->rbt_distances = NULL;
+       result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt_distances);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       for (i = 0; i < domain_names_count; i++) {
+               size_t *n;
+               dns_fixedname_t fname;
+               dns_name_t *name;
+               dns_test_namefromstring(domain_names[i], &fname);
+               name = dns_fixedname_name(&fname);
+               n = isc_mem_get(mctx, sizeof(size_t));
+               *n = i + 1;
+               result = dns_rbt_addname(ctx->rbt, name, n);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               n = isc_mem_get(mctx, sizeof(size_t));
+               *n = node_distances[i];
+               result = dns_rbt_addname(ctx->rbt_distances, name, n);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       }
+       return (ctx);
+ }
+ static void
+ test_context_teardown(test_context_t *ctx) {
+       dns_rbt_destroy(&ctx->rbt);
+       dns_rbt_destroy(&ctx->rbt_distances);
+       isc_mem_put(mctx, ctx, sizeof(*ctx));
+ }
+ /*
+  * Walk the tree and ensure that all the test nodes are present.
+  */
+ static void
+ check_test_data(dns_rbt_t *rbt) {
+       dns_fixedname_t fixed;
+       isc_result_t result;
+       dns_name_t *foundname;
+       size_t i;
+       dns_fixedname_init(&fixed);
+       foundname = dns_fixedname_name(&fixed);
+       for (i = 0; i < domain_names_count; i++) {
+               dns_fixedname_t fname;
+               dns_name_t *name;
+               size_t *n;
+               dns_test_namefromstring(domain_names[i], &fname);
+               name = dns_fixedname_name(&fname);
+               n = NULL;
+               result = dns_rbt_findname(rbt, name, 0, foundname,
+                                         (void *) &n);
+               ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+               ATF_CHECK_EQ(*n, i + 1);
+       }
+ }
+ ATF_TC(rbt_create);
+ ATF_TC_HEAD(rbt_create, tc) {
+       atf_tc_set_md_var(tc, "descr", "Test the creation of an rbt");
+ }
+ ATF_TC_BODY(rbt_create, tc) {
+       isc_result_t result;
+       test_context_t *ctx;
 -      tree_ok = dns__rbt_checkproperties(ctx->rbt);
 -      ATF_CHECK_EQ(tree_ok, ISC_TRUE);
 -
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       check_test_data(ctx->rbt);
 -              const size_t *distance = (const size_t *) node->data;
 -              if (distance != NULL)
 -                      ATF_CHECK_EQ(*distance,
 -                                   dns__rbtnode_getdistance(node));
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_nodecount);
+ ATF_TC_HEAD(rbt_nodecount, tc) {
+       atf_tc_set_md_var(tc, "descr", "Test dns_rbt_nodecount() on a tree");
+ }
+ ATF_TC_BODY(rbt_nodecount, tc) {
+       isc_result_t result;
+       test_context_t *ctx;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbtnode_get_distance);
+ ATF_TC_HEAD(rbtnode_get_distance, tc) {
+       atf_tc_set_md_var(tc, "descr",
+                         "Test dns_rbtnode_get_distance() on a tree");
+ }
+ ATF_TC_BODY(rbtnode_get_distance, tc) {
+       isc_result_t result;
+       test_context_t *ctx;
+       const char *name_str = "a";
+       dns_fixedname_t fname;
+       dns_name_t *name;
+       dns_rbtnode_t *node = NULL;
+       dns_rbtnodechain_t chain;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       dns_test_namefromstring(name_str, &fname);
+       name = dns_fixedname_name(&fname);
+       dns_rbtnodechain_init(&chain, mctx);
+       result = dns_rbt_findnode(ctx->rbt_distances, name, NULL,
+                                 &node, &chain, 0, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       while (node != NULL) {
 -      isc_boolean_t tree_ok;
+               result = dns_rbtnodechain_next(&chain, NULL, NULL);
+               if (result == ISC_R_NOMORE)
+                     break;
+               dns_rbtnodechain_current(&chain, NULL, NULL, &node);
+       }
+       ATF_CHECK_EQ(result, ISC_R_NOMORE);
+       dns_rbtnodechain_invalidate(&chain);
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_check_distance_random);
+ ATF_TC_HEAD(rbt_check_distance_random, tc) {
+       atf_tc_set_md_var(tc, "descr",
+                         "Test tree balance, inserting names in random order");
+ }
+ ATF_TC_BODY(rbt_check_distance_random, tc) {
+       /* This test checks an important performance-related property of
+        * the red-black tree, which is important for us: the longest
+        * path from a sub-tree's root to a node is no more than
+        * 2log(n). This check verifies that the tree is balanced.
+        */
+       dns_rbt_t *mytree = NULL;
+       const unsigned int log_num_nodes = 16;
+       int i;
+       isc_result_t result;
 -      /* The distance from each node to its sub-tree root must be less
 -       * than 2 * log(n).
 -       */
 -      ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
 -
 -      /* Also check RB tree properties */
 -      tree_ok = dns__rbt_checkproperties(mytree);
 -      ATF_CHECK_EQ(tree_ok, ISC_TRUE);
 -
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /* Names are inserted in random order. */
+       /* Make a large 65536 node top-level domain tree, i.e., the
+        * following code inserts names such as:
+        *
+        * savoucnsrkrqzpkqypbygwoiliawpbmz.
+        * wkadamcbbpjtundbxcmuayuycposvngx.
+        * wzbpznemtooxdpjecdxynsfztvnuyfao.
+        * yueojmhyffslpvfmgyfwioxegfhepnqq.
+        */
+       for (i = 0; i < (1 << log_num_nodes); i++) {
+               size_t *n;
+               char namebuf[34];
+               n = isc_mem_get(mctx, sizeof(size_t));
+               *n = i + 1;
+               while (1) {
+                       int j;
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       for (j = 0; j < 32; j++) {
+                               isc_uint32_t v;
+                               isc_random_get(&v);
+                               namebuf[j] = 'a' + (v % 26);
+                       }
+                       namebuf[32] = '.';
+                       namebuf[33] = 0;
+                       dns_test_namefromstring(namebuf, &fname);
+                       name = dns_fixedname_name(&fname);
+                       result = dns_rbt_addname(mytree, name, n);
+                       if (result == ISC_R_SUCCESS)
+                               break;
+               }
+       }
+       /* 1 (root . node) + (1 << log_num_nodes) */
+       ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
 -      isc_boolean_t tree_ok;
+       dns_rbt_destroy(&mytree);
+       dns_test_end();
+ }
+ ATF_TC(rbt_check_distance_ordered);
+ ATF_TC_HEAD(rbt_check_distance_ordered, tc) {
+       atf_tc_set_md_var(tc, "descr",
+                         "Test tree balance, inserting names in sorted order");
+ }
+ ATF_TC_BODY(rbt_check_distance_ordered, tc) {
+       /* This test checks an important performance-related property of
+        * the red-black tree, which is important for us: the longest
+        * path from a sub-tree's root to a node is no more than
+        * 2log(n). This check verifies that the tree is balanced.
+        */
+       dns_rbt_t *mytree = NULL;
+       const unsigned int log_num_nodes = 16;
+       int i;
+       isc_result_t result;
 -      /* The distance from each node to its sub-tree root must be less
 -       * than 2 * log(n).
 -       */
 -      ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
 -
 -      /* Also check RB tree properties */
 -      tree_ok = dns__rbt_checkproperties(mytree);
 -      ATF_CHECK_EQ(tree_ok, ISC_TRUE);
 -
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /* Names are inserted in sorted order. */
+       /* Make a large 65536 node top-level domain tree, i.e., the
+        * following code inserts names such as:
+        *
+        *   name00000000.
+        *   name00000001.
+        *   name00000002.
+        *   name00000003.
+        */
+       for (i = 0; i < (1 << log_num_nodes); i++) {
+               size_t *n;
+               char namebuf[14];
+               dns_fixedname_t fname;
+               dns_name_t *name;
+               n = isc_mem_get(mctx, sizeof(size_t));
+               *n = i + 1;
+               snprintf(namebuf, sizeof(namebuf), "name%08x.", i);
+               dns_test_namefromstring(namebuf, &fname);
+               name = dns_fixedname_name(&fname);
+               result = dns_rbt_addname(mytree, name, n);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       }
+       /* 1 (root . node) + (1 << log_num_nodes) */
+       ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
 -              isc_boolean_t tree_ok;
+       dns_rbt_destroy(&mytree);
+       dns_test_end();
+ }
+ static isc_result_t
+ insert_helper(dns_rbt_t *rbt, const char *namestr, dns_rbtnode_t **node) {
+       dns_fixedname_t fname;
+       dns_name_t *name;
+       dns_test_namefromstring(namestr, &fname);
+       name = dns_fixedname_name(&fname);
+       return (dns_rbt_addnode(rbt, name, node));
+ }
+ static isc_boolean_t
+ compare_labelsequences(dns_rbtnode_t *node, const char *labelstr) {
+       dns_name_t name;
+       isc_result_t result;
+       char *nodestr = NULL;
+       isc_boolean_t is_equal;
+       dns_name_init(&name, NULL);
+       dns_rbt_namefromnode(node, &name);
+       result = dns_name_tostring(&name, &nodestr, mctx);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       is_equal = strcmp(labelstr, nodestr) == 0 ? ISC_TRUE : ISC_FALSE;
+       isc_mem_free(mctx, nodestr);
+       return (is_equal);
+ }
+ ATF_TC(rbt_insert);
+ ATF_TC_HEAD(rbt_insert, tc) {
+       atf_tc_set_md_var(tc, "descr", "Test insertion into a tree");
+ }
+ ATF_TC_BODY(rbt_insert, tc) {
+       isc_result_t result;
+       test_context_t *ctx;
+       dns_rbtnode_t *node;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       /* Check node count before beginning. */
+       ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
+       /* Try to insert a node that already exists. */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_EXISTS);
+       /* Node count must not have changed. */
+       ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
+       /* Try to insert a node that doesn't exist. */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "0", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "0"), ISC_TRUE);
+       /* Node count must have increased. */
+       ATF_CHECK_EQ(16, dns_rbt_nodecount(ctx->rbt));
+       /* Another. */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "example.com", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE(node != NULL);
+       ATF_CHECK_EQ(node->data, NULL);
+       /* Node count must have increased. */
+       ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
+       /* Re-adding it should return EXISTS */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "example.com", &node);
+       ATF_CHECK_EQ(result, ISC_R_EXISTS);
+       /* Node count must not have changed. */
+       ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
+       /* Fission the node d.e.f */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "k.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "k"), ISC_TRUE);
+       /* Node count must have incremented twice ("d.e.f" fissioned to
+        * "d" and "e.f", and the newly added "k").
+        */
+       ATF_CHECK_EQ(19, dns_rbt_nodecount(ctx->rbt));
+       /* Fission the node "g.h" */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "h", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "h"), ISC_TRUE);
+       /* Node count must have incremented ("g.h" fissioned to "g" and
+        * "h").
+        */
+       ATF_CHECK_EQ(20, dns_rbt_nodecount(ctx->rbt));
+       /* Add child domains */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "m.p.w.y.d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "m"), ISC_TRUE);
+       ATF_CHECK_EQ(21, dns_rbt_nodecount(ctx->rbt));
+       node = NULL;
+       result = insert_helper(ctx->rbt, "n.p.w.y.d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "n"), ISC_TRUE);
+       ATF_CHECK_EQ(22, dns_rbt_nodecount(ctx->rbt));
+       node = NULL;
+       result = insert_helper(ctx->rbt, "l.a", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(compare_labelsequences(node, "l"), ISC_TRUE);
+       ATF_CHECK_EQ(23, dns_rbt_nodecount(ctx->rbt));
+       node = NULL;
+       result = insert_helper(ctx->rbt, "r.d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "s.d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ATF_CHECK_EQ(25, dns_rbt_nodecount(ctx->rbt));
+       node = NULL;
+       result = insert_helper(ctx->rbt, "h.w.y.d.e.f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       /* Add more nodes one by one to cover left and right rotation
+        * functions.
+        */
+       node = NULL;
+       result = insert_helper(ctx->rbt, "f", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "m", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "nm", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "om", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "k", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "l", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "fe", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "ge", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "i", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "ae", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       node = NULL;
+       result = insert_helper(ctx->rbt, "n", &node);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_remove);
+ ATF_TC_HEAD(rbt_remove, tc) {
+       atf_tc_set_md_var(tc, "descr", "Test removal from a tree");
+ }
+ ATF_TC_BODY(rbt_remove, tc) {
+       /*
+        * This testcase checks that after node removal, the
+        * binary-search tree is valid and all nodes that are supposed
+        * to exist are present in the correct order. It mainly tests
+        * DomainTree as a BST, and not particularly as a red-black
+        * tree. This test checks node deletion when upper nodes have
+        * data.
+        */
+       isc_result_t result;
+       size_t j;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /*
+        * Delete single nodes and check if the rest of the nodes exist.
+        */
+       for (j = 0; j < ordered_names_count; j++) {
+               dns_rbt_t *mytree = NULL;
+               dns_rbtnode_t *node;
+               size_t i;
+               size_t *n;
 -              /* Check RB tree properties. */
 -              tree_ok = dns__rbt_checkproperties(mytree);
 -              ATF_CHECK_EQ(tree_ok, ISC_TRUE);
 -
+               dns_rbtnodechain_t chain;
+               size_t start_node;
+               /* Create a tree. */
+               result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               /* Insert test data into the tree. */
+               for (i = 0; i < domain_names_count; i++) {
+                       node = NULL;
+                       result = insert_helper(mytree, domain_names[i], &node);
+                       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               }
+               /* Check that all names exist in order. */
+               for (i = 0; i < ordered_names_count; i++) {
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       dns_test_namefromstring(ordered_names[i], &fname);
+                       name = dns_fixedname_name(&fname);
+                       node = NULL;
+                       result = dns_rbt_findnode(mytree, name, NULL,
+                                                 &node, NULL,
+                                                 DNS_RBTFIND_EMPTYDATA,
+                                                 NULL, NULL);
+                       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+                       /* Add node data */
+                       ATF_REQUIRE(node != NULL);
+                       ATF_REQUIRE_EQ(node->data, NULL);
+                       n = isc_mem_get(mctx, sizeof(size_t));
+                       *n = i;
+                       node->data = n;
+               }
+               /* Now, delete the j'th node from the tree. */
+               {
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       dns_test_namefromstring(ordered_names[j], &fname);
+                       name = dns_fixedname_name(&fname);
+                       result = dns_rbt_deletename(mytree, name, ISC_FALSE);
+                       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+               }
 -      isc_boolean_t tree_ok;
 -
+               dns_rbtnodechain_init(&chain, mctx);
+               /* Now, walk through nodes in order. */
+               if (j == 0) {
+                       /*
+                        * Node for ordered_names[0] was already deleted
+                        * above. We start from node 1.
+                        */
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       dns_test_namefromstring(ordered_names[0], &fname);
+                       name = dns_fixedname_name(&fname);
+                       node = NULL;
+                       result = dns_rbt_findnode(mytree, name, NULL,
+                                                 &node, NULL,
+                                                 0,
+                                                 NULL, NULL);
+                       ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
+                       dns_test_namefromstring(ordered_names[1], &fname);
+                       name = dns_fixedname_name(&fname);
+                       node = NULL;
+                       result = dns_rbt_findnode(mytree, name, NULL,
+                                                 &node, &chain,
+                                                 0,
+                                                 NULL, NULL);
+                       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+                       start_node = 1;
+               } else {
+                       /* Start from node 0. */
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       dns_test_namefromstring(ordered_names[0], &fname);
+                       name = dns_fixedname_name(&fname);
+                       node = NULL;
+                       result = dns_rbt_findnode(mytree, name, NULL,
+                                                 &node, &chain,
+                                                 0,
+                                                 NULL, NULL);
+                       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+                       start_node = 0;
+               }
+               /*
+                * node and chain have been set by the code above at
+                * this point.
+                */
+               for (i = start_node; i < ordered_names_count; i++) {
+                       dns_fixedname_t fname_j, fname_i;
+                       dns_name_t *name_j, *name_i;
+                       dns_test_namefromstring(ordered_names[j], &fname_j);
+                       name_j = dns_fixedname_name(&fname_j);
+                       dns_test_namefromstring(ordered_names[i], &fname_i);
+                       name_i = dns_fixedname_name(&fname_i);
+                       if (dns_name_equal(name_i, name_j)) {
+                               /*
+                                * This may be true for the last node if
+                                * we seek ahead in the loop using
+                                * dns_rbtnodechain_next() below.
+                                */
+                               if (node == NULL) {
+                                       break;
+                               }
+                               /* All ordered nodes have data
+                                * initially. If any node is empty, it
+                                * means it was removed, but an empty
+                                * node exists because it is a
+                                * super-domain. Just skip it.
+                                */
+                               if (node->data == NULL) {
+                                       result = dns_rbtnodechain_next(&chain,
+                                                                      NULL,
+                                                                      NULL);
+                                       if (result == ISC_R_NOMORE) {
+                                               node = NULL;
+                                       } else {
+                                               dns_rbtnodechain_current(&chain,
+                                                                        NULL,
+                                                                        NULL,
+                                                                        &node);
+                                       }
+                               }
+                               continue;
+                       }
+                       ATF_REQUIRE(node != NULL);
+                       n = (size_t *) node->data;
+                       if (n != NULL) {
+                               /* printf("n=%zu, i=%zu\n", *n, i); */
+                               ATF_CHECK_EQ(*n, i);
+                       }
+                       result = dns_rbtnodechain_next(&chain, NULL, NULL);
+                       if (result == ISC_R_NOMORE) {
+                               node = NULL;
+                       } else {
+                               dns_rbtnodechain_current(&chain, NULL, NULL,
+                                                        &node);
+                       }
+               }
+               /* We should have reached the end of the tree. */
+               ATF_REQUIRE_EQ(node, NULL);
+               dns_rbt_destroy(&mytree);
+       }
+       dns_test_end();
+ }
+ static void
+ insert_nodes(dns_rbt_t *mytree, char **names,
+            size_t *names_count, isc_uint32_t num_names)
+ {
+       isc_uint32_t i;
+       dns_rbtnode_t *node;
+       for (i = 0; i < num_names; i++) {
+               size_t *n;
+               char namebuf[34];
+               n = isc_mem_get(mctx, sizeof(size_t));
+               ATF_REQUIRE(n != NULL);
+               *n = i; /* Unused value */
+               while (1) {
+                       int j;
+                       dns_fixedname_t fname;
+                       dns_name_t *name;
+                       isc_result_t result;
+                       for (j = 0; j < 32; j++) {
+                               isc_uint32_t v;
+                               isc_random_get(&v);
+                               namebuf[j] = 'a' + (v % 26);
+                       }
+                       namebuf[32] = '.';
+                       namebuf[33] = 0;
+                       dns_test_namefromstring(namebuf, &fname);
+                       name = dns_fixedname_name(&fname);
+                       node = NULL;
+                       result = dns_rbt_addnode(mytree, name, &node);
+                       if (result == ISC_R_SUCCESS) {
+                               node->data = n;
+                               names[*names_count] = isc_mem_strdup(mctx,
+                                                                    namebuf);
+                               *names_count += 1;
+                               break;
+                       }
+               }
+       }
+ }
+ static void
+ remove_nodes(dns_rbt_t *mytree, char **names,
+            size_t *names_count, isc_uint32_t num_names)
+ {
+       isc_uint32_t i;
+       UNUSED(mytree);
+       for (i = 0; i < num_names; i++) {
+               isc_uint32_t node;
+               dns_fixedname_t fname;
+               dns_name_t *name;
+               isc_result_t result;
+               isc_random_get(&node);
+               node %= *names_count;
+               dns_test_namefromstring(names[node], &fname);
+               name = dns_fixedname_name(&fname);
+               result = dns_rbt_deletename(mytree, name, ISC_FALSE);
+               ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+               isc_mem_free(mctx, names[node]);
+               if (*names_count > 0) {
+                       names[node] = names[*names_count - 1];
+                       names[*names_count - 1] = NULL;
+                       *names_count -= 1;
+               }
+       }
+ }
+ static void
+ check_tree(dns_rbt_t *mytree, char **names, size_t names_count,
+          unsigned int line)
+ {
 -
 -      /*
 -       * The distance from each node to its sub-tree root must be less
 -       * than 2 * log_2(1024).
 -       */
 -      ATF_CHECK((2 * 10) >= dns__rbt_getheight(mytree));
 -
 -      /* Also check RB tree properties */
 -      tree_ok = dns__rbt_checkproperties(mytree);
 -      ATF_CHECK_EQ(tree_ok, ISC_TRUE);
+       UNUSED(names);
+       ATF_CHECK_EQ_MSG(names_count + 1, dns_rbt_nodecount(mytree),
+                        "line:%u: %lu != %u", line,
+                        (unsigned long)(names_count + 1),
+                        dns_rbt_nodecount(mytree));
+ }
+ ATF_TC(rbt_insert_and_remove);
+ ATF_TC_HEAD(rbt_insert_and_remove, tc) {
+       atf_tc_set_md_var(tc, "descr",
+                         "Test insert and remove in a loop");
+ }
+ ATF_TC_BODY(rbt_insert_and_remove, tc) {
+       /*
+        * What is the best way to test our red-black tree code? It is
+        * not a good method to test every case handled in the actual
+        * code itself. This is because our approach itself may be
+        * incorrect.
+        *
+        * We test our code at the interface level here by exercising the
+        * tree randomly multiple times, checking that red-black tree
+        * properties are valid, and all the nodes that are supposed to be
+        * in the tree exist and are in order.
+        *
+        * NOTE: These tests are run within a single tree level in the
+        * forest. The number of nodes in the tree level doesn't grow
+        * over 1024.
+        */
+       isc_result_t result;
+       dns_rbt_t *mytree = NULL;
+       /*
+        * We use an array for storing names instead of a set
+        * structure. It's slow, but works and is good enough for tests.
+        */
+       char *names[1024];
+       size_t names_count;
+       int i;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       memset(names, 0, sizeof(names));
+       names_count = 0;
+       /* Repeat the insert/remove test some 4096 times */
+       for (i = 0; i < 4096; i++) {
+               isc_uint32_t num_names;
+               isc_random_get(&num_names);
+               if (names_count < 1024) {
+                       num_names %= 1024 - names_count;
+                       num_names++;
+               } else {
+                       num_names = 0;
+               }
+               insert_nodes(mytree, names, &names_count, num_names);
+               check_tree(mytree, names, names_count, __LINE__);
+               isc_random_get(&num_names);
+               if (names_count > 0) {
+                       num_names %= names_count;
+                       num_names++;
+               } else {
+                       num_names = 0;
+               }
+               remove_nodes(mytree, names, &names_count, num_names);
+               check_tree(mytree, names, names_count, __LINE__);
+       }
+       /* Remove the rest of the nodes */
+       remove_nodes(mytree, names, &names_count, names_count);
+       check_tree(mytree, names, names_count, __LINE__);
+       for (i = 0; i < 1024; i++) {
+               if (names[i] != NULL) {
+                       isc_mem_free(mctx, names[i]);
+               }
+       }
+       dns_rbt_destroy(&mytree);
+       dns_test_end();
+ }
+ ATF_TC(rbt_findname);
+ ATF_TC_HEAD(rbt_findname, tc) {
+       atf_tc_set_md_var(tc, "descr", "findname return values");
+ }
+ ATF_TC_BODY(rbt_findname, tc) {
+       isc_result_t result;
+       test_context_t *ctx = NULL;
+       dns_fixedname_t fname, found;
+       dns_name_t *name = NULL, *foundname = NULL;
+       size_t *n = NULL;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       /* Try to find a name that exists. */
+       dns_test_namefromstring("d.e.f", &fname);
+       name = dns_fixedname_name(&fname);
+       dns_fixedname_init(&found);
+       foundname = dns_fixedname_name(&found);
+       result = dns_rbt_findname(ctx->rbt, name,
+                                 DNS_RBTFIND_EMPTYDATA,
+                                 foundname, (void *) &n);
+       ATF_CHECK(dns_name_equal(foundname, name));
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       /* Now without EMPTYDATA */
+       result = dns_rbt_findname(ctx->rbt, name, 0,
+                                 foundname, (void *) &n);
+       ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
+       /* Now one that partially matches */
+       dns_test_namefromstring("d.e.f.g.h.i.j", &fname);
+       name = dns_fixedname_name(&fname);
+       result = dns_rbt_findname(ctx->rbt, name,
+                                 DNS_RBTFIND_EMPTYDATA,
+                                 foundname, (void *) &n);
+       ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH);
+       /* Now one that doesn't match */
+       dns_test_namefromstring("1.2", &fname);
+       name = dns_fixedname_name(&fname);
+       result = dns_rbt_findname(ctx->rbt, name,
+                                 DNS_RBTFIND_EMPTYDATA,
+                                 foundname, (void *) &n);
+       ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH);
+       ATF_CHECK(dns_name_equal(foundname, dns_rootname));
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_addname);
+ ATF_TC_HEAD(rbt_addname, tc) {
+       atf_tc_set_md_var(tc, "descr", "addname return values");
+ }
+ ATF_TC_BODY(rbt_addname, tc) {
+       isc_result_t result;
+       test_context_t *ctx = NULL;
+       dns_fixedname_t fname;
+       dns_name_t *name = NULL;
+       size_t *n;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       n = isc_mem_get(mctx, sizeof(size_t));
+       *n = 1;
+       dns_test_namefromstring("d.e.f.g.h.i.j.k", &fname);
+       name = dns_fixedname_name(&fname);
+       /* Add a name that doesn't exist */
+       result = dns_rbt_addname(ctx->rbt, name, n);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /* Now add again, should get ISC_R_EXISTS */
+       n = isc_mem_get(mctx, sizeof(size_t));
+       *n = 2;
+       result = dns_rbt_addname(ctx->rbt, name, n);
+       ATF_REQUIRE_EQ(result, ISC_R_EXISTS);
+       isc_mem_put(mctx, n, sizeof(size_t));
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_deletename);
+ ATF_TC_HEAD(rbt_deletename, tc) {
+       atf_tc_set_md_var(tc, "descr", "deletename return values");
+ }
+ ATF_TC_BODY(rbt_deletename, tc) {
+       isc_result_t result;
+       test_context_t *ctx = NULL;
+       dns_fixedname_t fname;
+       dns_name_t *name = NULL;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       /* Delete a name that doesn't exist */
+       dns_test_namefromstring("z.x.y.w", &fname);
+       name = dns_fixedname_name(&fname);
+       result = dns_rbt_deletename(ctx->rbt, name, ISC_FALSE);
+       ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
+       /* Now one that does */
+       dns_test_namefromstring("d.e.f", &fname);
+       name = dns_fixedname_name(&fname);
+       result = dns_rbt_deletename(ctx->rbt, name, ISC_FALSE);
+       ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ ATF_TC(rbt_nodechain);
+ ATF_TC_HEAD(rbt_nodechain, tc) {
+       atf_tc_set_md_var(tc, "descr", "nodechain");
+ }
+ ATF_TC_BODY(rbt_nodechain, tc) {
+       isc_result_t result;
+       test_context_t *ctx;
+       dns_fixedname_t fname, found, expect;
+       dns_name_t *name, *foundname, *expected;
+       dns_rbtnode_t *node = NULL;
+       dns_rbtnodechain_t chain;
+       UNUSED(tc);
+       isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       ctx = test_context_setup();
+       dns_rbtnodechain_init(&chain, mctx);
+       dns_test_namefromstring("a", &fname);
+       name = dns_fixedname_name(&fname);
+       result = dns_rbt_findnode(ctx->rbt, name, NULL,
+                                 &node, &chain, 0, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       dns_fixedname_init(&found);
+       foundname = dns_fixedname_name(&found);
+       dns_test_namefromstring("a", &expect);
+       expected = dns_fixedname_name(&expect);
+       UNUSED(expected);
+       result = dns_rbtnodechain_first(&chain, ctx->rbt, foundname, NULL);
+       ATF_CHECK_EQ(result, DNS_R_NEWORIGIN);
+       ATF_CHECK_EQ(dns_name_countlabels(foundname), 0);
+       result = dns_rbtnodechain_prev(&chain, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_NOMORE);
+       result = dns_rbtnodechain_next(&chain, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       result = dns_rbtnodechain_next(&chain, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL);
+       ATF_CHECK_EQ(result, DNS_R_NEWORIGIN);
+       result = dns_rbtnodechain_next(&chain, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_NOMORE);
+       result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL);
+       ATF_CHECK_EQ(result, DNS_R_NEWORIGIN);
+       result = dns_rbtnodechain_prev(&chain, NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       dns_rbtnodechain_invalidate(&chain);
+       test_context_teardown(ctx);
+       dns_test_end();
+ }
+ #ifdef ISC_PLATFORM_USETHREADS
+ #ifdef DNS_BENCHMARK_TESTS
+ /*
+  * XXXMUKS: Don't delete this code. It is useful in benchmarking the
+  * RBT, but we don't require it as part of the unit test runs.
+  */
+ ATF_TC(benchmark);
+ ATF_TC_HEAD(benchmark, tc) {
+       atf_tc_set_md_var(tc, "descr", "Benchmark RBT implementation");
+ }
+ static dns_fixedname_t *fnames;
+ static dns_name_t **names;
+ static int *values;
+ static void *
+ find_thread(void *arg) {
+       dns_rbt_t *mytree;
+       isc_result_t result;
+       dns_rbtnode_t *node;
+       unsigned int j, i;
+       unsigned int start = 0;
+       mytree = (dns_rbt_t *) arg;
+       while (start == 0)
+               start = random() % 4000000;
+       /* Query 32 million random names from it in each thread */
+       for (j = 0; j < 8; j++) {
+               for (i = start; i != start - 1; i = (i + 1) % 4000000) {
+                       node = NULL;
+                       result = dns_rbt_findnode(mytree, names[i], NULL,
+                                                 &node, NULL,
+                                                 DNS_RBTFIND_EMPTYDATA,
+                                                 NULL, NULL);
+                       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+                       ATF_REQUIRE(node != NULL);
+                       ATF_CHECK_EQ(values[i], (intptr_t) node->data);
+               }
+       }
+       return (NULL);
+ }
+ ATF_TC_BODY(benchmark, tc) {
+       isc_result_t result;
+       char namestr[sizeof("name18446744073709551616.example.org.")];
+       unsigned int r;
+       dns_rbt_t *mytree;
+       dns_rbtnode_t *node;
+       unsigned int i;
+       unsigned int maxvalue = 1000000;
+       isc_time_t ts1, ts2;
+       double t;
+       unsigned int nthreads;
+       isc_thread_t threads[32];
+       UNUSED(tc);
+       srandom(time(NULL));
+       debug_mem_record = ISC_FALSE;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       fnames = (dns_fixedname_t *) malloc(4000000 * sizeof(dns_fixedname_t));
+       names = (dns_name_t **) malloc(4000000 * sizeof(dns_name_t *));
+       values = (int *) malloc(4000000 * sizeof(int));
+       for (i = 0; i < 4000000; i++) {
+                 r = ((unsigned long) random()) % maxvalue;
+                 snprintf(namestr, sizeof(namestr), "name%u.example.org.", r);
+                 dns_test_namefromstring(namestr, &fnames[i]);
+                 names[i] = dns_fixedname_name(&fnames[i]);
+                 values[i] = r;
+       }
+       /* Create a tree. */
+       mytree = NULL;
+       result = dns_rbt_create(mctx, NULL, NULL, &mytree);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       /* Insert test data into the tree. */
+       for (i = 0; i < maxvalue; i++) {
+               snprintf(namestr, sizeof(namestr), "name%u.example.org.", i);
+               node = NULL;
+               result = insert_helper(mytree, namestr, &node);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+               node->data = (void *) (intptr_t) i;
+       }
+       result = isc_time_now(&ts1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       nthreads = ISC_MIN(isc_os_ncpus(), 32);
+       nthreads = ISC_MAX(nthreads, 1);
+       for (i = 0; i < nthreads; i++) {
+               result = isc_thread_create(find_thread, mytree, &threads[i]);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       }
+       for (i = 0; i < nthreads; i++) {
+               result = isc_thread_join(threads[i], NULL);
+               ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       }
+       result = isc_time_now(&ts2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       t = isc_time_microdiff(&ts2, &ts1);
+       printf("%u findnode calls, %f seconds, %f calls/second\n",
+              nthreads * 8 * 4000000, t / 1000000.0,
+              (nthreads * 8 * 4000000) / (t / 1000000.0));
+       free(values);
+       free(names);
+       free(fnames);
+       dns_rbt_destroy(&mytree);
+       dns_test_end();
+ }
+ #endif /* DNS_BENCHMARK_TESTS */
+ #endif /* ISC_PLATFORM_USETHREADS */
+ /*
+  * Main
+  */
+ ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, rbt_create);
+       ATF_TP_ADD_TC(tp, rbt_nodecount);
+       ATF_TP_ADD_TC(tp, rbtnode_get_distance);
+       ATF_TP_ADD_TC(tp, rbt_check_distance_random);
+       ATF_TP_ADD_TC(tp, rbt_check_distance_ordered);
+       ATF_TP_ADD_TC(tp, rbt_insert);
+       ATF_TP_ADD_TC(tp, rbt_remove);
+       ATF_TP_ADD_TC(tp, rbt_insert_and_remove);
+       ATF_TP_ADD_TC(tp, rbt_findname);
+       ATF_TP_ADD_TC(tp, rbt_addname);
+       ATF_TP_ADD_TC(tp, rbt_deletename);
+       ATF_TP_ADD_TC(tp, rbt_nodechain);
+ #ifdef ISC_PLATFORM_USETHREADS
+ #ifdef DNS_BENCHMARK_TESTS
+       ATF_TP_ADD_TC(tp, benchmark);
+ #endif /* DNS_BENCHMARK_TESTS */
+ #endif /* ISC_PLATFORM_USETHREADS */
+       return (atf_no_error());
+ }
index 0000000000000000000000000000000000000000,67fbe05627359233966094db7bf746eb7820b687..f6e53b1f802a8f7d0d8b7601126606fcefd77a49
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,233 +1,233 @@@
 -      dns_resolver_settimeout(resolver, default_timeout + 100);
+ /*
+  * Copyright (C) 2018  Internet Systems Consortium, Inc. ("ISC")
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ /*! \file */
+ #include <config.h>
+ #include <atf-c.h>
+ #include <unistd.h>
+ #include <isc/app.h>
+ #include <isc/buffer.h>
+ #include <isc/socket.h>
+ #include <isc/task.h>
+ #include <isc/timer.h>
+ #include <dns/dispatch.h>
+ #include <dns/name.h>
+ #include <dns/resolver.h>
+ #include <dns/view.h>
+ #include "dnstest.h"
+ static dns_dispatchmgr_t *dispatchmgr = NULL;
+ static dns_dispatch_t *dispatch = NULL;
+ static dns_view_t *view = NULL;
+ static void
+ setup(void) {
+       isc_result_t result;
+       isc_sockaddr_t local;
+       result = dns_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = dns_test_makeview("view", &view);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_sockaddr_any(&local);
+       result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &local,
+                                    4096, 100, 100, 100, 500, 0, 0,
+                                    &dispatch);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ }
+ static void
+ teardown(void) {
+       dns_dispatch_detach(&dispatch);
+       dns_view_detach(&view);
+       dns_dispatchmgr_destroy(&dispatchmgr);
+       dns_test_end();
+ }
+ static void
+ mkres(dns_resolver_t **resolverp) {
+       isc_result_t result;
+       result = dns_resolver_create(view, taskmgr, 1, 1,
+                           socketmgr, timermgr, 0,
+                           dispatchmgr, dispatch, NULL, resolverp);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ }
+ static void
+ destroy_resolver(dns_resolver_t **resolverp) {
+       dns_resolver_shutdown(*resolverp);
+       dns_resolver_detach(resolverp);
+ }
+ ATF_TC(create);
+ ATF_TC_HEAD(create, tc) {
+       atf_tc_set_md_var(tc, "descr", "dns_resolver_create");
+ }
+ ATF_TC_BODY(create, tc) {
+       dns_resolver_t *resolver = NULL;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ ATF_TC(gettimeout);
+ ATF_TC_HEAD(gettimeout, tc) {
+       atf_tc_set_md_var(tc, "descr", "dns_resolver_gettimeout");
+ }
+ ATF_TC_BODY(gettimeout, tc) {
+       dns_resolver_t *resolver = NULL;
+       unsigned int timeout;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       timeout = dns_resolver_gettimeout(resolver);
+       ATF_CHECK(timeout > 0);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ ATF_TC(settimeout);
+ ATF_TC_HEAD(settimeout, tc) {
+       atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout");
+ }
+ ATF_TC_BODY(settimeout, tc) {
+       dns_resolver_t *resolver = NULL;
+       unsigned int default_timeout, timeout;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       default_timeout = dns_resolver_gettimeout(resolver);
+       dns_resolver_settimeout(resolver, default_timeout + 1);
+       timeout = dns_resolver_gettimeout(resolver);
+       ATF_CHECK(timeout == default_timeout + 1);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ ATF_TC(settimeout_default);
+ ATF_TC_HEAD(settimeout_default, tc) {
+       atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout to default");
+ }
+ ATF_TC_BODY(settimeout_default, tc) {
+       dns_resolver_t *resolver = NULL;
+       unsigned int default_timeout, timeout;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       default_timeout = dns_resolver_gettimeout(resolver);
 -      ATF_CHECK_EQ(timeout, default_timeout + 100);
++      dns_resolver_settimeout(resolver, default_timeout + 10);
+       timeout = dns_resolver_gettimeout(resolver);
 -      dns_resolver_settimeout(resolver, 9000);
++      ATF_CHECK_EQ(timeout, default_timeout + 10);
+       dns_resolver_settimeout(resolver, 0);
+       timeout = dns_resolver_gettimeout(resolver);
+       ATF_CHECK_EQ(timeout, default_timeout);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ ATF_TC(settimeout_belowmin);
+ ATF_TC_HEAD(settimeout_belowmin, tc) {
+       atf_tc_set_md_var(tc, "descr",
+                         "dns_resolver_settimeout below minimum");
+ }
+ ATF_TC_BODY(settimeout_belowmin, tc) {
+       dns_resolver_t *resolver = NULL;
+       unsigned int default_timeout, timeout;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       default_timeout = dns_resolver_gettimeout(resolver);
++      dns_resolver_settimeout(resolver, 9);
+       timeout = dns_resolver_gettimeout(resolver);
+       ATF_CHECK_EQ(timeout, default_timeout);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ ATF_TC(settimeout_overmax);
+ ATF_TC_HEAD(settimeout_overmax, tc) {
+       atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout over maximum");
+ }
+ ATF_TC_BODY(settimeout_overmax, tc) {
+       dns_resolver_t *resolver = NULL;
+       unsigned int timeout;
+       UNUSED(tc);
+       setup();
+       mkres(&resolver);
+       dns_resolver_settimeout(resolver, 4000000);
+       timeout = dns_resolver_gettimeout(resolver);
+       ATF_CHECK(timeout < 4000000 && timeout > 0);
+       destroy_resolver(&resolver);
+       teardown();
+ }
+ /*
+  * Main
+  */
+ ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, create);
+       ATF_TP_ADD_TC(tp, gettimeout);
+       ATF_TP_ADD_TC(tp, settimeout);
+       ATF_TP_ADD_TC(tp, settimeout_default);
+       ATF_TP_ADD_TC(tp, settimeout_belowmin);
+       ATF_TP_ADD_TC(tp, settimeout_overmax);
+       return (atf_no_error());
+ }
index be413a8e3def2832e9d467c7dbf22ef8cbff110b,d539dee4d31544f052a8748355833f16d5dbfbaa..ce05e0298405872caeb4eb6eea40e1ac2c728942
@@@ -16,7 -18,7 +18,7 @@@ atf_test_program{name='radix_test'
  atf_test_program{name='regex_test'}
  atf_test_program{name='safe_test'}
  atf_test_program{name='sockaddr_test'}
--atf_test_program{name='socket_test'}
++atf_test_program{name='socket_test', is_exclusive=true}
  atf_test_program{name='symtab_test'}
  atf_test_program{name='task_test'}
  atf_test_program{name='taskpool_test'}
index f252b3b7983e52921e98d9b949993fead0070dc9,d974afd00aeabc379fa5c480c180c4f4006ce702..ce0a7ed50bc6150a3df1c1277f182d05ede8f772
@@@ -38,12 -40,14 +40,14 @@@ SRCS =             isctest.c atomic_test.c 
                parse_test.c pool_test.c print_test.c queue_test.c \
                radix_test.c regex_test.c safe_test.c sockaddr_test.c \
                socket_test.c symtab_test.c task_test.c taskpool_test.c \
-               time_test.c
+               time_test.c timer_test.c
  
  SUBDIRS =
- TARGETS =     counter_test@EXEEXT@ errno_test@EXEEXT@ hash_test@EXEEXT@ \
+ TARGETS =     atomic_test@EXEEXT@ counter_test@EXEEXT@ \
+               errno_test@EXEEXT@ hash_test@EXEEXT@ \
                heap_test@EXEEXT@ inet_ntop_test@EXEEXT@ lex_test@EXEEXT@ \
-               netaddr_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \
 -              mem_test@ExEEXT@ netaddr_test@EXEEXT@ \
++              mem_test@EXEEXT@ netaddr_test@EXEEXT@ \
+               parse_test@EXEEXT@ pool_test@EXEEXT@ \
                print_test@EXEEXT@ queue_test@EXEEXT@ radix_test@EXEEXT@ \
                regex_test@EXEEXT@ safe_test@EXEEXT@ sockaddr_test@EXEEXT@ \
                socket_test@EXEEXT@ socket_test@EXEEXT@ symtab_test@EXEEXT@ \
index 0000000000000000000000000000000000000000,25c2585e3913411166ad4a3ffe447e3428e9204c..9a8371ac400902b5010356705e45f34adb808b90
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,263 +1,195 @@@
 -ATF_TC(isc_mem_total);
 -ATF_TC_HEAD(isc_mem_total, tc) {
 -      atf_tc_set_md_var(tc, "descr", "test TotalUse calculation");
 -}
 -
 -ATF_TC_BODY(isc_mem_total, tc) {
 -      isc_result_t result;
 -      isc_mem_t *mctx2 = NULL;
 -      size_t before, after;
 -      ssize_t diff;
 -      int i;
 -
 -      result = isc_test_begin(NULL, ISC_TRUE, 0);
 -      ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
 -
 -      /* Local alloc, free */
 -      mctx2 = NULL;
 -      result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
 -                                NULL, &mctx2, 0);
 -      if (result != ISC_R_SUCCESS)
 -              goto out;
 -
 -      before = isc_mem_total(mctx2);
 -
 -      for (i = 0; i < 100000; i++) {
 -              void *ptr;
 -
 -              ptr = isc_mem_allocate(mctx2, 2048);
 -              isc_mem_free(mctx2, ptr);
 -      }
 -
 -      after = isc_mem_total(mctx2);
 -      diff = after - before;
 -
 -      printf("total_before=%lu, total_after=%lu, total_diff=%lu\n",
 -             (unsigned long)before, (unsigned long)after,
 -             (unsigned long)diff);
 -      /* 2048 +8 bytes extra for size_info */
 -      ATF_CHECK_EQ(diff, (2048 + 8) * 100000);
 -
 -      /* ISC_MEMFLAG_INTERNAL */
 -
 -      before = isc_mem_total(mctx);
 -
 -      for (i = 0; i < 100000; i++) {
 -              void *ptr;
 -
 -              ptr = isc_mem_allocate(mctx, 2048);
 -              isc_mem_free(mctx, ptr);
 -      }
 -
 -      after = isc_mem_total(mctx);
 -      diff = after - before;
 -
 -      printf("total_before=%lu, total_after=%lu, total_diff=%lu\n",
 -             (unsigned long)before, (unsigned long)after,
 -             (unsigned long)diff);
 -      /* 2048 +8 bytes extra for size_info */
 -      ATF_CHECK_EQ(diff, (2048 + 8) * 100000);
 -
 - out:
 -      if (mctx2 != NULL)
 -              isc_mem_destroy(&mctx2);
 -
 -      isc_test_end();
 -}
 -
+ /*
+  * Copyright (C) 2018  Internet Systems Consortium, Inc. ("ISC")
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ #include <config.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <atf-c.h>
+ #include "isctest.h"
+ #include <isc/mem.h>
+ #include <isc/print.h>
+ #include <isc/result.h>
+ static void *
+ default_memalloc(void *arg, size_t size) {
+       UNUSED(arg);
+       if (size == 0U)
+               size = 1;
+       return (malloc(size));
+ }
+ static void
+ default_memfree(void *arg, void *ptr) {
+       UNUSED(arg);
+       free(ptr);
+ }
+ ATF_TC(isc_mem);
+ ATF_TC_HEAD(isc_mem, tc) {
+       atf_tc_set_md_var(tc, "descr", "general memory system tests");
+ }
+ #define       MP1_FREEMAX     10
+ #define       MP1_FILLCNT     10
+ #define       MP1_MAXALLOC    30
+ #define       MP2_FREEMAX     25
+ #define       MP2_FILLCNT     25
+ ATF_TC_BODY(isc_mem, tc) {
+       isc_result_t result;
+       void *items1[50];
+       void *items2[50];
+       void *tmp;
+       isc_mem_t *localmctx = NULL;
+       isc_mempool_t *mp1 = NULL, *mp2 = NULL;
+       unsigned int i, j;
+       int rval;
+       result = isc_test_begin(NULL, ISC_TRUE, 0);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_mem_create(0, 0, &localmctx);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_mempool_create(localmctx, 24, &mp1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_mempool_create(localmctx, 31, &mp2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_mempool_setfreemax(mp1, MP1_FREEMAX);
+       isc_mempool_setfillcount(mp1, MP1_FILLCNT);
+       isc_mempool_setmaxalloc(mp1, MP1_MAXALLOC);
+       /*
+        * Allocate MP1_MAXALLOC items from the pool.  This is our max.
+        */
+       for (i = 0; i < MP1_MAXALLOC; i++) {
+               items1[i] = isc_mempool_get(mp1);
+               ATF_CHECK(items1[i] != NULL);
+       }
+       /*
+        * Try to allocate one more.  This should fail.
+        */
+       tmp = isc_mempool_get(mp1);
+       ATF_CHECK_EQ(tmp, NULL);
+       /*
+        * 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;
+       }
+       rval = isc_mempool_getfreecount(mp1);
+       ATF_CHECK_EQ(rval, 10);
+       rval = isc_mempool_getallocated(mp1);
+       ATF_CHECK_EQ(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);
+                       ATF_CHECK(items2[i] != NULL);
+               }
+               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_mem_destroy(&localmctx);
+       isc_test_end();
+ }
 -      ATF_TP_ADD_TC(tp, isc_mem_total);
+ ATF_TC(isc_mem_inuse);
+ ATF_TC_HEAD(isc_mem_inuse, tc) {
+       atf_tc_set_md_var(tc, "descr", "test InUse calculation");
+ }
+ ATF_TC_BODY(isc_mem_inuse, tc) {
+       isc_result_t result;
+       isc_mem_t *mctx2 = NULL;
+       size_t before, during, after;
+       ssize_t diff;
+       void *ptr;
+       result = isc_test_begin(NULL, ISC_TRUE, 0);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       mctx2 = NULL;
+       result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
+                                 NULL, &mctx2, 0);
+       if (result != ISC_R_SUCCESS)
+               goto out;
+       before = isc_mem_inuse(mctx2);
+       ptr = isc_mem_allocate(mctx2, 1024000);
+       during = isc_mem_inuse(mctx2);
+       isc_mem_free(mctx2, ptr);
+       after = isc_mem_inuse(mctx2);
+       diff = after - before;
+       printf("inuse_before=%lu, inuse_during=%lu, inuse_after=%lu\n",
+              (unsigned long)before, (unsigned long)during,
+              (unsigned long)after);
+       ATF_REQUIRE_EQ(diff, 0);
+  out:
+       if (mctx2 != NULL)
+               isc_mem_destroy(&mctx2);
+       isc_test_end();
+ }
+ /*
+  * Main
+  */
+ ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, isc_mem);
+       ATF_TP_ADD_TC(tp, isc_mem_inuse);
+       return (atf_no_error());
+ }