#!/bin/bash

# this script runs the dnsproxy-standalone test program and runs a couple of
# standard DNS queries against it, using the currently configured DNS server
# in the system as dnsproxy configuration.

echoerr() {
	echo $@ 1>&2
	echo -e "\n   >>> ERROR OCCURED <<<   \n" 1>&2
	exit 1
}


showlog() {
	if [ -z "$SHOW_LOG" -o -z "$logfile" ]; then
		return
	fi

	echo
	echo "======== debug log ==========="
	cat "$logfile"
	echo "===== end debug log =========="
	echo
}

TRANSPORTS="-U -T"

while [ $# -gt 0 ]; do
	case "$1" in
	"--valgrind")
		VALGRIND=`which valgrind`
		if [ -z "$VALGRIND" ]; then
			echoerr "no valgrind executable found"
		fi
		# log valgrind output to stdout, since stderr is used for
		# debug output from dnsproxy.c already and we want to parse
		# that.
		# also cause an error exit it valgrind error occur so that
		# they're easily noticed.
		VALGRIND="$VALGRIND --log-fd=1 --error-exitcode=10"
		;;
	"--gdb")
		WAIT_GDB=1
		# wait forever to avoid timeout conditions during debugging
		HOST_OPTS="-w"
		;;
	"--show-log")
		SHOW_LOG=1
		;;
	"--testdomain="*)
		TESTDOMAIN=`echo $1 | cut -d '=' -f2-`
		CUSTOM_TESTDOMAIN=1
		;;
	"--only-tcp")
		TRANSPORTS="-T"
		;;
	"--only-udp")
		TRANSPORTS="-U"
		;;
	"-h")
		echo "$0 [--valgrind] [--gdb] [--show-log] [--only-tcp] [--only-udp] [--testdomain=<mydomain>]"
		echo "--valgrind: run dnsproxy-standalone in valgrind"
		echo "--gdb: allows you to attach via GDB before tests are started"
		echo "--show-log: dump debug log from dnsproxy at end of test"
		echo "--only-tcp: only perform TCP protocol based tests"
		echo "--only-udp: only perform UDP protocol based tests"
		echo "--testdomain=<mydomain>: the domain name to resolve"
		exit 2
		;;
	*)
		echoerr "Unknown argument $1"
		;;
	esac
	shift
done

if [ -n "$VALGRIND" -a -n "$WAIT_GDB" ]; then
	echo "Cannot mix valgrind frontend and GDB attachment" 1>&2
	exit 2
fi

if [ -e "Makefile" ]; then
	BUILDROOT="$PWD"
else
	if [ ! -n "$BUILDROOT" ]; then
		echoerr "You need to set the BUILDROOT environment variable or run this script from the connman build tree root"
	fi

	pushd "$BUILDROOT" >/dev/null || echoerr "couldn't enter $BUILDROOT"
fi
make tools/dnsproxy-standalone || echoerr "failed to build dnsproxy-standalone"

HOST=`which host`
if [ -z "$HOST" ]; then
	echoerr "Couldn't find 'host' DNS utility"
fi

DNSPROXY="$BUILDROOT/tools/dnsproxy-standalone"

if [ ! -f "$DNSPROXY" ]; then
	echoerr "standalone dnsproxy does not exist at $DNSPROXY"
fi

NS1=`grep -w nameserver -m 1 /etc/resolv.conf | cut -d ' ' -f 2`
if [ -z "$NS1" ]; then
	echoerr "Failed to determine system's nameserver from /etc/resolv.conf"
fi

DOMAIN1=`grep -w search -m 1 /etc/resolv.conf | cut -d ' ' -f 2`
if [ -z "$DOMAIN1" ]; then
	echoerr "Failed to determine default DNS domain from /etc/resolv.conf"
fi

# use an unprivileged port for the proxy so we don't need special permissions
# to run this test
PORT=8053

# run the proxy in the background
logfile=`mktemp`
$VALGRIND $DNSPROXY $PORT "$DOMAIN1" "$NS1" 2>"$logfile" &
proxy_pid=$!

cleanup() {
	if [ $proxy_pid -eq -1 ]; then
		return 0
	fi
	kill $proxy_pid
	wait $proxy_pid
	ret=$?
	proxy_pid=-1
	if [ -n "$logfile" ]; then
		if [ -n "$SHOW_LOG" ]; then
			showlog
		fi
		rm -f "$logfile"
		unset logfile
	fi
	return $ret
}

trap cleanup err exit

sleep 1
echo -e "\n\n"

if [ -n "$WAIT_GDB" ]; then
	echo "You can now attach to the dnsproxy process at PID $proxy_pid."
	echo "Press ENTER to continue test execution"
	read _
fi

if [ -z "$TESTDOMAIN" ]; then
	TESTDOMAIN="www.example.com"
fi

# perform each test twice to actually get cached responses served for each
# combination
for I in `seq 2`; do
	# test both UDP and TCP mode
	for TRANSPORT in $TRANSPORTS; do
		# test both IPv4 and IPv6
		for IP in -4 -6; do
			echo "Testing resolution using transport $TRANSPORT and IP${IP}"
			set -x
			$HOST $HOST_OPTS $TRANSPORT $IP -p$PORT $TESTDOMAIN 127.0.0.1
			RES=$?
			set +x
			if [ $RES -ne 0 ]; then
				echoerr "resolution failed"
			fi

			echo -e "\n\n"
		done
	done
done

NUM_HITS=`grep "cache hit.*$TESTDOMAIN" "$logfile" | wc -l`

echo -e "\n\nDNS resolution succeeded for all test combinations"
echo -e "\nNumber of cache hits: $NUM_HITS\n"
# assert we have seen the expected number of cache hits in the log
# this is the amount of cache hits for the default domain tests as seen before
# refactoring of dnsproxy started.
if [ -z "$CUSTOM_TESTDOMAIN" -a "$NUM_HITS" -ne 15 ]; then
	echoerr "Unexpected number of cache hits encountered"
elif [ "$NUM_HITS" -lt 8 ]; then
	echoerr "Too low number of cache hits encountered"
fi
cleanup
if [ $? -eq 0 ]; then
	exit 0
else
	echoerr "dnsproxy returned non-zero exit status $?"
fi

