# #-- 09-unbound-control.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test

PRE="../.."
. ../common.sh

# End the test
# $1: exit value
end () {
	echo "> cat logfiles"
	cat fwd.log 
	cat unbound.log
	exit $1
}

# Expect a given exit value of the previous command
# $1: the expected exit value
# $2: optional text to print when failing
expect_exit_value () {
	if test $? -ne $1; then
		if test -z "$2"; then
			if test $1 -eq 1; then
				msg="on error"
			else
				msg="after success"
			fi
		else
			msg="$2"
		fi
		echo "wrong exit value $msg"
		end 1
	fi
}

# Helper function for quering
# $@: at least the domain name to query and optional dig arguments
query () {
	echo "> dig $@"
	dig @127.0.0.1 -p $UNBOUND_PORT $@ | tee outfile
}

# Expect something in the answer
# $1: expected regular expression
expect_answer () {
	echo "> check answer for \"$1\""
	if grep "$1" outfile; then
		echo "OK"
	else
		echo "Not OK"
		end 1
	fi
}

# Fail the test for unexpected answers
# $1: unexpected regular expression
fail_answer () {
	echo "> \"$1\" should not be in answer"
	if grep "$1" outfile; then
		echo "Not OK"
		end 1
	else
		echo "OK"
	fi
}

# Issue an unbound-control command
# $@: command arguments
control_command () {
	echo "$PRE/unbound-control $@"
	$PRE/unbound-control $@ > outfile
}

# Dump the cache contents
# $@: optional options to unbound-control
cache_dump () {
	echo "$PRE/unbound-control $@ dump_cache > cache.dump"
	$PRE/unbound-control $@ dump_cache > cache.dump
}

# Load cache contents
# $@: optional options to unbound-control
cache_load () {
	echo "$PRE/unbound-control $@ load_cache < cache.dump"
	$PRE/unbound-control $@ load_cache < cache.dump
}

# Expect an entry in the cache dump
# $1: expected regular expression
expect_in_cache_dump () {
	echo "> check cache dump for \"$1\""
	if grep "$1" cache.dump; then
		echo "OK cache dump"
	else
		echo "Not OK cache dump"
		end 1
	fi
}

# Fail the test for unexpected entry in the cache dump
# $1: unexpected regular expression
fail_in_cache_dump () {
	echo "> \"$1\" should not be in cache dump"
	if grep "$1" cache.dump; then
		echo "Not OK cache dump"
		end 1
	else
		echo "OK cache dump"
	fi
}

# start the test
cp ub.conf main.conf

teststep "exit value is 1 on usage"
control_command -h
expect_exit_value 1 "for usage"

# use lock-verify if possible

teststep "test if the server is up"
query www.example.com.
expect_answer "10.20.30.40"

teststep "exit value is 1 when a bad command is given"
control_command -c ub.conf blablargh
expect_exit_value 1

# reload the server. test if the server came up by putting a new
# local-data element in the server.
teststep "reload the server"
echo "server: local-data: 'afterreload. IN A 5.6.7.8'" >> ub.conf
control_command -c ub.conf reload
expect_exit_value 0
query afterreload.
expect_answer "5.6.7.8"

teststep "must have had at least 1 query since reload"
control_command -c ub.conf stats
expect_exit_value 0
expect_answer "^total.num.queries=[1-9][0-9]*$"

teststep "check verbosity"
control_command -c ub.conf verbosity 2
expect_exit_value 0

teststep "check syntax error in parse"
control_command -c ub.conf verbosity jkdf
expect_exit_value 1

teststep "check bad credentials"
cp ub.conf bad.conf
cat conf.bad_credentials >> bad.conf
control_command -c bad.conf verbosity 2
expect_exit_value 1

teststep "check spoofed client credentials"
rm -f bad.conf
cp ub.conf bad.conf
cat conf.spoofed_credentials >> bad.conf
control_command -c bad.conf verbosity 2
expect_exit_value 1

teststep "create a new local zone"
control_command -c ub.conf local_zone example.net static
expect_exit_value 0
control_command -c ub.conf local_data www.example.net A 192.0.2.1
expect_exit_value 0

teststep "check that www.example.net exists"
query www.example.net.
expect_answer "192.0.2.1"

teststep "check that mail.example.net has nxdomain"
query mail.example.net.
expect_answer "NXDOMAIN"

teststep "remove www.example.net - check it gets nxdomain"
control_command -c ub.conf local_data_remove www.example.net
expect_exit_value 0
query www.example.net.
expect_answer "NXDOMAIN"

teststep "remove nonexistent name - check bug#287(segfault) does not happen"
control_command -c ub.conf local_data_remove test.example.net
# if crash then then we get: error: could not SSL_read from unbound-control
expect_exit_value 0

teststep "remove example.net - check its gone"
control_command -c ub.conf local_zone_remove example.net
expect_exit_value 0
query www.example.net.
expect_answer "SERVFAIL"

teststep "dump the cache"
query www.example.com.
cache_dump -c ub.conf
expect_exit_value 0
cat cache.dump
expect_in_cache_dump "10.20.30.40"

control_command -c ub.conf lookup www.example.com
expect_exit_value 0
# answer to lookup is meaningless because of use a forwarder, oh well.

teststep "load the cache dump"
cache_load -c ub.conf
expect_exit_value 0
query www.example.com.
expect_answer "10.20.30.40"

teststep "load local-zones from file"
control_command -c ub.conf local_zones < local_zones
expect_exit_value 0
query localzonefromfile
expect_answer "REFUSED"

teststep "load local-data from file"
control_command -c ub.conf local_datas < local_data
expect_exit_value 0
query -t txt localdatafromfile
expect_answer "local data from file OK"

teststep "remove local-zone and local-data from file"
control_command -c ub.conf local_zones_remove < local_zones_remove
expect_exit_value 0
control_command -c ub.conf local_datas_remove < local_data_remove
expect_exit_value 0
control_command -c ub.conf list_local_zones
fail_answer "localzonefromfile"
fail_answer "local data from file OK"
expect_answer "otherlocalzone"

teststep "flushing"
control_command -c ub.conf flush www.example.net
expect_exit_value 0
control_command -c ub.conf flush_type www.example.net TXT
expect_exit_value 0
control_command -c ub.conf flush_zone example.net
expect_exit_value 0

teststep "reload the server for a clean state and populate the cache"
cp main.conf ub.conf
control_command -c ub.conf reload
expect_exit_value 0
query www.example.com
expect_answer "10.20.30.40"

teststep "reload and check cache dump - should be empty"
control_command -c ub.conf reload
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
fail_in_cache_dump "www.example.com.*10.20.30.40"
fail_in_cache_dump "msg www.example.com. IN A"

query www.example.com
expect_answer "10.20.30.40"

teststep "reload_keep_cache and check cache dump - should not be empty"
control_command -c ub.conf reload_keep_cache
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
cat cache.dump
expect_in_cache_dump "www.example.com.*10.20.30.40"
expect_in_cache_dump "msg www.example.com. IN A"
query www.example.com +nordflag
expect_answer "10.20.30.40"

teststep "change msg-cache-size and reload_keep_cache - should be empty"
echo "server: msg-cache-size: 2m" >> ub.conf
control_command -c ub.conf reload_keep_cache
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
fail_in_cache_dump "www.example.com.*10.20.30.40"
fail_in_cache_dump "msg www.example.com. IN A"
query www.example.com
expect_answer "10.20.30.40"

teststep "change rrset-cache-size and reload_keep_cache - should be empty"
echo "server: rrset-cache-size: 2m" >> ub.conf
control_command -c ub.conf reload_keep_cache
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
fail_in_cache_dump "www.example.com.*10.20.30.40"
fail_in_cache_dump "msg www.example.com. IN A"
query www.example.com
expect_answer "10.20.30.40"

# See if this part of the test can be enabled, it needs threads for combined
# output.
have_threads="no"
if grep "define HAVE_PTHREAD 1" $PRE/config.h; then have_threads="yes"; fi
if grep "define HAVE_SOLARIS_THREADS 1" $PRE/config.h; then have_threads="yes"; fi
if grep "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then have_threads="yes"; fi
if test "$have_threads" = "yes"; then

teststep "change num-threads and reload_keep_cache - should be empty"
echo "server: num-threads: 2" >> ub.conf
control_command -c ub.conf reload_keep_cache
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
fail_in_cache_dump "www.example.com.*10.20.30.40"
fail_in_cache_dump "msg www.example.com. IN A"
query www.example.com
expect_answer "10.20.30.40"

teststep "change minimal-responses and reload_keep_cache - should not be empty"
echo "server: minimal-responses: no" >> ub.conf
control_command -c ub.conf reload_keep_cache
expect_exit_value 0
cache_dump -c ub.conf
expect_exit_value 0
expect_in_cache_dump "www.example.com.*10.20.30.40"
expect_in_cache_dump "msg www.example.com. IN A"

else
	echo ""
	echo "> skip test parts that need threads, have_threads=no"
# end of check for have_threads
fi

teststep "now stop the server"
control_command -c ub.conf stop
expect_exit_value 0

teststep "see if the server has really exited"
TRY_MAX=20
for (( try=0 ; try <= $TRY_MAX ; try++ )) ; do
	if kill -0 $UNBOUND_PID 2>&1 | tee tmp.$$; then
		echo "not stopped yet, waiting"
		sleep 1
	else
		echo "stopped OK; break"
		break;
	fi
	if grep "No such process" tmp.$$; then
		echo "stopped OK; break"
		break;
	fi
done
if kill -0 $UNBOUND_PID; then
	echo "still up!"
	echo "not stopped, failure"
	end 1
else
	echo "stopped OK"

        if test -f ublocktrace.0; then
		if $PRE/lock-verify ublocktrace.*; then
			echo "lock-verify test worked."
		else
			echo "lock-verify test failed."
			end 1
		fi
	fi
fi

end 0
