diff --git a/configure.ac b/configure.ac index c54da52bee..5a9a0da3c1 100644 --- a/configure.ac +++ b/configure.ac @@ -965,6 +965,7 @@ AC_OUTPUT([doc/version.ent tests/system/glue/setup.sh tests/system/glue/nsx1/b10-config.db tests/system/bindctl/nsx1/b10-config.db.template + tests/system/ixfr/ixfr_init.sh tests/system/ixfr/in-1/setup.sh tests/system/ixfr/in-1/tests.sh tests/system/ixfr/in-1/nsx2/b10-config.db @@ -997,6 +998,7 @@ AC_OUTPUT([doc/version.ent chmod +x src/lib/python/isc/log/tests/log_console.py chmod +x tests/system/conf.sh chmod +x tests/system/run.sh + chmod +x tests/system/ixfr/ixfr_init.sh chmod +x tests/system/ixfr/in-1/setup.sh chmod +x tests/system/ixfr/in-1/tests.sh ]) diff --git a/tests/system/README b/tests/system/README index a43d49edb4..a1c0a9781f 100644 --- a/tests/system/README +++ b/tests/system/README @@ -5,48 +5,49 @@ See COPYRIGHT in the source root or http://isc.org/copyright.html for terms. This is a simple test environment for running BIND 10 system tests involving multiple name servers. It was originally developed for BIND 9, and has been ported to test BIND 10 implementations. Ideally we -should share the same framework for both versions, so some part of -the original setup are kept, even though they are BIND 9 specific and -not currently used. +should share the same framework for both versions, so some part of the +original setup are kept, even though they are BIND 9 specific and not +currently used. -Also, these tests generally rely on BIND 9 programs, most commonly its -dig, and will sometimes be its name server (named). So, the test +Also, these tests generally rely on BIND 9 programs, most commonly +its dig, and will sometimes be its name server (named). So, the test environment assumes that there's a source tree of BIND 9 where its -programs are built, and that an environment variable "BIND9_TOP" is -set to point to the top directory of the source tree. +programs are built, and that an environment variable "BIND9_TOP" is set +to point to the top directory of the source tree. There are multiple test suites, each in a separate subdirectory and involving a different DNS setup. They are: bindctl/ Some basic management operations using the bindctl tool - glue/ Glue handling tests + glue/ Glue handling tests + ixfr/ Incremental transfer tests + (the following tests are planned to be added soon) - dnssec/ DNSSEC tests + dnssec/ DNSSEC tests masterfile/ Master file parser - xfer/ Zone transfer tests + axfr/ Full-transfer tests Typically each test suite sets up 2-5 instances of BIND 10 (or BIND 9 -named) and then performs one or more tests against them. Within the -test suite subdirectory, each instance has a separate subdirectory -containing its configuration data. By convention, these -subdirectories are named "nsx1", "nsx2", etc for BIND 10 ("x" means -BIND 10), and "ns1", "ns2", etc. for BIND 9. +named) and then performs one or more tests against them. Within the test +suite subdirectory, each instance has a separate subdirectory containing +its configuration data. By convention, these subdirectories are named +"nsx1", "nsx2", etc for BIND 10 ("x" means BIND 10), and "ns1", "ns2", +etc. for BIND 9. The tests are completely self-contained and do not require access to -the real DNS. Generally, one of the test servers (ns[x]1) is set up -as a root name server and is listed in the hints file of the others. +the real DNS. Generally, one of the test servers (ns[x]1) is set up as +a root name server and is listed in the hints file of the others. -To enable all servers to run on the same machine, they bind to -separate virtual IP address on the loopback interface. ns[x]1 runs on -10.53.0.1, ns[x]2 on 10.53.0.2, etc. Before running any tests, you -must set up these addresses by running "ifconfig.sh up" as root. +To enable all servers to run on the same machine, they bind to separate +virtual IP address on the loopback interface. ns[x]1 runs on 10.53.0.1, +ns[x]2 on 10.53.0.2, etc. Before running any tests, you must set up +these addresses by running "ifconfig.sh up" as root. Mac OS X: -If you wish to make the interfaces survive across reboots -copy org.isc.bind.system and org.isc.bind.system to -/Library/LaunchDaemons then run -"launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist" as -root. +If you wish to make the interfaces survive across reboots copy +org.isc.bind.system and org.isc.bind.system to /Library/LaunchDaemons +then run "launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist" +as root. The servers use port 53210 instead of the usual port 53, so they can be run without root privileges once the interfaces have been set up. diff --git a/tests/system/conf.sh.in b/tests/system/conf.sh.in index 5de00efeb5..2fdd3fed67 100755 --- a/tests/system/conf.sh.in +++ b/tests/system/conf.sh.in @@ -51,7 +51,7 @@ export RNDC=$BIND9_TOP/bin/rndc/rndc export TESTSOCK=$BIND9_TOP/bin/tests/system/testsock.pl export DIGCOMP=$BIND9_TOP/bin/tests/system/digcomp.pl -export SUBDIRS="bindctl glue" +export SUBDIRS="bindctl glue ixfr/in-1" #SUBDIRS="dnssec masterfile xfer" # PERL will be an empty string if no perl interpreter was found. A similar diff --git a/tests/system/ixfr/in-1/setup.sh.in b/tests/system/ixfr/in-1/setup.sh.in index 7c34c2bcef..ac2d78d557 100644 --- a/tests/system/ixfr/in-1/setup.sh.in +++ b/tests/system/ixfr/in-1/setup.sh.in @@ -21,11 +21,11 @@ sh clean.sh -# Set up the IXFR server - Load an old version of the zone. +# Set up the initial version of the IXFR server - Load an old version of the zone. cp -f ns1/named_nonotify.conf ns1/named.conf cp -f $IXFR_TOP/largezone_n-4.db ns1/zone.db -# Set up the IXFR client +# Set up the IXFR client - load the same version of the zone. ${B10_LOADZONE} -o . -d @builddir@/nsx2/zone.sqlite3 $IXFR_TOP/largezone_n-4.db diff --git a/tests/system/ixfr/in-1/tests.sh.in b/tests/system/ixfr/in-1/tests.sh.in index 1884c89e5a..a7ed151f98 100644 --- a/tests/system/ixfr/in-1/tests.sh.in +++ b/tests/system/ixfr/in-1/tests.sh.in @@ -27,94 +27,32 @@ # file to ensure that the debug message recording the sending of the IXFR # request and the receipt of the single update is recorded. -. @abs_top_builddir@/tests/system/conf.sh +. ../ixfr_init.sh -IXFR_SERVER=10.53.0.1 # BIND 9 -IXFR_CLIENT=10.53.0.2 # BIND 10 +SERVER_NAME=ns1 +SERVER_IP=10.53.0.1 # BIND 9 -# Short-hand for getting SOA - just supply address of the server -DIG_SOA="$DIG +norecurse +short -p $DNS_PORT example. SOA" +CLIENT_NAME=nsx2 +CLIENT_IP=10.53.0.2 # BIND 10 status=0 -# do_rndc -# -# Controls the BIND 9 IXFR server. Called do_rndc (instead of rndc) to avoid -# confusion if rndc itself is in the search path. -# -# $* - Command to execute (which may be multiple tokens) -do_rndc () { - $RNDC -c $SYSTEM_TOP/common/rndc.conf -s $IXFR_SERVER -p $RNDC_PORT $* 2>&1 \ - | sed 's/^/I:ns1 /' -} - -# wait_for_update -# -# Given a serial number and a server, poll the nameserver until the SOA serial -# number is different from that given. The poll takes place every five seconds -# for a minute. -# -# $1 - Server to check -# $2 - Serial number to check against -# -# Returns: -# 0 - Serial number is different (requires another poll to obatin it) -# 1 - Serial number has not changed -wait_for_update() { - for i in 1 2 3 4 5 6 7 8 9 10 11 12 - do - new_serial=`$DIG_SOA @$1 | $AWK '{print $3}'` - if [ "$new_serial" != "$2" ]; - then - break - fi - sleep 5 - done - - if [ "$new_serial" = "$2" ]; - then - return 1 - fi - return 0 -} - - - -# update_server_zone -# -# Reloads the example. zone in the IXFR server and waits a maximum of 50 -# seconds for it to be served. -# -# $1 - Name of new zone file (should be in the default directory). -update_server_zone() { - old_serial=`$DIG_SOA @$IXFR_SERVER | $AWK '{print $3}'` - echo "I:ns1 IXFR server loading $1" - cp $1 ns1/zone.db - do_rndc reload - wait_for_update $IXFR_SERVER $old_serial - - if [ $? -ne 0 ]; - then - echo "R:ns1 FAIL IXFR server did not update zone after reload" - return 1 - fi - - new_serial=`$DIG_SOA @$IXFR_SERVER | $AWK '{print $3}'` - echo "R:ns1 IXFR server was at serial $old_serial, now at $new_serial" - return 0 -} - # The current state of the nameservers is that they should both be running the # "n - 4" version of the zone. -# + +# Store the SOA serial number of the BIND 10 client for later use. + +old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'` +echo "I:SOA serial of IXFR client is $old_client_serial" + # Load the BIND 9 system (the IXFR server) with the "n - 2" and "n" version of # the zones. With ixfr-from-differences set to "yes", the nameserver should # generate the differences between them. echo "I:updating IXFR-server for ixfr-in tests" - -update_server_zone $IXFR_TOP/largezone_n-2.db -if [ $? != 0 ]; then +update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/largezone_n-2.db +if [ $? != 0 ]; +then status=1 fi @@ -122,8 +60,9 @@ fi # the second sometimes gets lost. sleep 5 -update_server_zone $IXFR_TOP/largezone_n-0.db -if [ $? != 0 ]; then +update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/largezone_n-0.db +if [ $? != 0 ]; +then status=1 fi @@ -132,20 +71,43 @@ fi echo "I:notifying IXFR-client of presence of new zones" cp ns1/named_notify.conf ns1/named.conf -do_rndc reconfig -do_rndc notify example -# Store the SOA serial number of the latest zone in the BIND 9 server -server_serial=`$DIG_SOA @$IXFR_SERVER | $AWK '{print $3}'` -echo "I:SOA serial of IXFR server is $server_serial" +do_rndc $SERVER_NAME $SERVER_IP reconfig +if [ $? != 0 ]; +then + status=1 +fi -client_serial=`$DIG_SOA @$IXFR_CLIENT | $AWK '{print $3}'` -echo "I:SOA serial of IXFR client is $client_serial" +# TODO: Need to alter configuration of BIND 10 server such that it accepts +# NOTIFYs from and sens IXFR requests to the BIND 9 master. -# Now compare the two zones - they should be the same. +do_rndc $SERVER_NAME $SERVER_IP notify example +if [ $? != 0 ]; +then + status=1 +fi -# Check the BIND 10 log, looking for the IXFR messages that -# indicate that it has initiated an IXFR. +# Wait for the client to update itself. + +wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial +if [ $? != 0 ]; +then + status=1 +fi + +# Has updated, get the latest serial of the client and server - they +# should be the same. +client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'` +server_serial=`$DIG_SOA @$SERVER_IP | $AWK '{print $3}'` +if [ "$client_serial" != "$server_serial" ]; +then + echo "I: FAIL - client serial not same as server serial after update" + status=1 +fi + +# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that +# it has initiated an IXFR and that it received the update within a single +# packet. echo "I:exit status: $status" exit $status diff --git a/tests/system/ixfr/ixfr_init.sh b/tests/system/ixfr/ixfr_init.sh new file mode 100755 index 0000000000..e7c6e5659c --- /dev/null +++ b/tests/system/ixfr/ixfr_init.sh @@ -0,0 +1,208 @@ +#!/bin/sh +# +# Copyright (C) 2011 Internet Software Consortium. +# +# 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 +# This file should be run by all IXFR tests before going anything else. It +# includes the main configuration script that defines the various environment +# variables, as well as defining useful shell subroutines. + +. /home/stephen/bind10/tests/system/conf.sh + +# Useful symbols used in the IXFR tests. + +# Short-hand for getting SOA - just supply address of the server +DIG_SOA="$DIG +norecurse +short -p $DNS_PORT example. SOA" + +# \brief Check Arguments +# +# All functions take the name of the server as the firsrt argument and its IP +# address as the second. This function is passed "$*" and just checks that +# both $1 and $2 are defined. +# +# \arg $* Arguments passed to caller +# +# \return status 0 => $1 and $2 are defined, 1 => they are not. +check_name_ip() { + + if [ "$1" = "" ]; + then + echo "R:FAIL name of server not supplied" + return 1 + fi + + if [ "$2" = "" ]; + then + echo "R:FAIL IP address of server not supplied" + return 1 + fi + + return 0 +} + + +# \brief Perform RNDC Command +# +# Controls the BIND 9 IXFR server. Called do_rndc (instead of rndc) to avoid +# confusion if rndc itself is in the search path. +# +# $1 - Name of the server (ns1, nsx2 etc.) +# $2 - IP address of the server +# $* - Command to execute (which may be multiple tokens) +do_rndc () { + + # If the following checks fail, the code is wrong. + + check_name_ip $* + if [ $? -ne 0 ]; + then + echo "R:FAIL do_rndc - name or ip address of server not supplied" + return 1 + fi + + name=$1 + shift + ip=$1 + shift + + if [ "$1" = "" ]; + then + echo "R:FAIL do_rndc - rndc command not supplied" + return 1 + fi + + $RNDC -c $SYSTEM_TOP/common/rndc.conf -s $ip -p $RNDC_PORT $* 2>&1 \ + | sed "s/^/I:$name /" +} + +# wait_for_update +# +# Given a serial number and a server, poll the nameserver until the SOA serial +# number is different from that given. The poll takes place every five seconds +# for a minute. +# +# $1 - Name of the server +# $2 - IP address of the server +# $3 - Serial number to check against +# +# Returns: +# 0 - Serial number is different (requires another poll to obtain it) +# 1 - Serial number has not changed +wait_for_update() { + + # If the following checks fail, the code is wrong. + + check_name_ip $* + if [ $? -ne 0 ]; + then + echo "R:FAIL wait_for_update - name or ip address of system not supplied" + return 1 + fi + + name=$1 + shift + ip=$1 + shift + + serial=$1 + shift + if [ "$serial" = "" ]; + then + echo "R:FAIL wait_for_update - serial number not supplied" + return 1 + fi + + # Now poll the server looking for the new serial number + + for i in 1 2 3 4 5 6 7 8 9 10 11 12 + do + if [ $i -gt 1 ]; + then + sleep 5 + fi + + new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` + if [ "$new_serial" != "$serial" ]; + then + return 0 + fi + done + + echo "R:$name FAIL serial number has not updated" + return 1 +} + + + +# update_server_zone +# +# Reloads the example. zone in the BIND 9 IXFR server and waits a maximum of +# one minute for it to be served. +# +# $1 - Name of the server (ns1, nsx2 etc.) +# $2 - IP address of the server +# $3 - Zone file to load +# $* - Command to execute (which may be multiple tokens) +update_server_zone() { + + # If the following checks fail, the code is wrong. + + check_name_ip $* + if [ $? -ne 0 ]; + then + echo "R:FAIL update_server_zone - name or ip address of server not supplied" + return 1 + fi + + name=$1 + shift + ip=$1 + shift + + file=$1 + shift + if [ "$file" = "" ]; + then + echo "R:FAIL update_server_zone - new zone file not supplied" + return 1 + fi + + if [ ! -e $file ]; + then + echo "R:FAIL update_server_zone - zone file does not exist: $file" + return 1 + fi + + old_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` + + echo "I:$name IXFR server loading $1" + cp $file $name/zone.db + do_rndc $name $ip reload + if [ $? -ne 0 ]; + then + return 1 # Message will have already been output + fi + + wait_for_update $name $ip $old_serial + if [ $? -ne 0 ]; + then + echo "R:$name FAIL IXFR server did not update zone after reload" + return 1 + fi + + new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` + echo "I:$name was at serial $old_serial, now at $new_serial" + return 0 +}