#!/bin/sh
set -e

TESTTORUN=''
while [ -n "$1" ]; do
	if [ "$1" = "-q" ]; then
		export MSGLEVEL=2
	elif [ "$1" = "-qq" ]; then
		export MSGLEVEL=1
	elif [ "$1" = "-v" ]; then
		export MSGLEVEL=4
	elif [ "$1" = '--color=no' ]; then
		export MSGCOLOR='NO'
	elif [ "$1" = '--color=yes' ]; then
		export MSGCOLOR='YES'
	elif [ "$1" = '--color' ]; then
		export MSGCOLOR="$(echo "$2" | tr 'a-z' 'A-Z')"
		shift
	elif [ "$1" = '--level' ]; then
		export MSGLEVEL=$2
		shift
	elif [ "$1" = '-j' ]; then
		APT_TEST_JOBS=$2
		shift
	elif [ -x "$1" ]; then
		TESTTORUN="$1"
	else
		echo >&2 "WARNING: Unknown parameter »$1« will be ignored"
	fi
	shift
done
export MSGLEVEL="${MSGLEVEL:-3}"

if [ "${MSGCOLOR:-YES}" = 'YES' ]; then
	if [ ! -t 1 ]; then # but check that we output to a terminal
		export MSGCOLOR='NO'
	fi
fi
if [ "$MSGCOLOR" != 'NO' ]; then
	CTEST='\033[1;32m'
	CHIGH='\033[1;35m'
	CRESET='\033[0m'
else
	CTEST=''
	CHIGH=''
	CRESET=''
fi

if [ -n "$TESTTORUN" ]; then
	# collecting the output of one test to have it together
	OUTPUT="$(mktemp)"
	CURRENTTRAP="rm -f \"$OUTPUT\"; $CURRENTTRAP"
	trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
	{
		if [ "$MSGLEVEL" -le 1 ]; then
			printf "${TESTTORUN##*/}"
		elif [ "$MSGLEVEL" -le 2 ]; then
			printf "${CTEST}Testcase ${CHIGH}${TESTTORUN##*/}${CRESET}: "
		else
			printf "${CTEST}Run Testcase ${CHIGH}${TESTTORUN##*/}${CRESET}\n"
		fi
		if ! "$TESTTORUN"; then
			FAIL='yes'
			if [ "$MSGLEVEL" -le 2 ]; then
				printf >&2 "\n${CHIGH}Running ${TESTTORUN##*/} -> FAILED${CRESET}\n"
			elif [ "$MSGLEVEL" -le 2 ]; then
				printf >&2 "\n${CHIGH}Running ${TESTTORUN##*/} -> FAILED${CRESET}"
			else
				echo >&2 "${CHIGH}Running ${TESTTORUN##*/} -> FAILED${CRESET}"
			fi
		else
			if [ "$MSGLEVEL" -le 1 ]; then
				printf " "
			fi
		fi
		if [ "$MSGLEVEL" -le 1 ]; then
			:
		elif [ "$MSGLEVEL" -le 2 ]; then
			echo
		fi
	} >"$OUTPUT" 2>&1
	# without we end up getting stepped output 'randomly'
	stty sane
	cat >&2 "$OUTPUT"
	stty sane
	if [ "$FAIL" = 'yes' ]; then
		exit 1
	else
		exit 0
	fi
fi

FAIL=0
PASS=0
ALL=0
FAILED_TESTS=""
DIR="$(readlink -f "$(dirname "$0")")"
cd "$DIR"
TESTLIST="$(find . -mindepth 1 -maxdepth 1 -regex '^\./test-[^/]*$' | sort)"
if [ -n "$APT_TEST_JOBS" ]; then
	if [ "$MSGCOLOR" != 'NO' ]; then
		export MSGCOLOR='ALWAYS'
	fi
	parallel=parallel
	if command -v moreutils-parallel >/dev/null 2>&1; then
		parallel=moreutils-parallel
	fi
	exec $parallel -j "$APT_TEST_JOBS" "./$(basename "$0")" -- $(echo "$TESTLIST")
fi

APT_TEST_SIGNINGHOME="$(mktemp --directory --tmpdir 'apt-key-signinghome.XXXXXXXXXX')"
removesigninghome() {
	if [ -z "$APT_TEST_SIGNINGHOME" ]; then return; fi
	GNUPGHOME="${APT_TEST_SIGNINGHOME}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true
	rm -rf -- "$APT_TEST_SIGNINGHOME"
}
trap "removesigninghome; exit 0" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
export APT_TEST_SIGNINGHOME

TOTAL="$(echo "$TESTLIST" | wc -l)"
if [ "$MSGLEVEL" -le 1 ]; then
	printf "${CTEST}Running testcases${CRESET}: "
fi
for testcase in $TESTLIST; do
	if [ "$MSGLEVEL" -le 1 ]; then
		printf "${testcase##*/}"
	elif [ "$MSGLEVEL" -le 2 ]; then
		printf "($(($ALL+1))/${TOTAL}) ${CTEST}Testcase ${CHIGH}${testcase##*/}${CRESET}: "
	else
		printf "${CTEST}Run Testcase ($(($ALL+1))/${TOTAL}) ${CHIGH}${testcase##*/}${CRESET}\n"
	fi
	if ! ${testcase}; then
		FAIL=$((FAIL+1))
		FAILED_TESTS="$FAILED_TESTS ${testcase##*/}"
		if [ "$MSGLEVEL" -le 1 ]; then
			printf >&2 "\n${CHIGH}Running ${testcase##*/} -> FAILED${CRESET}\n"
		elif [ "$MSGLEVEL" -le 2 ]; then
			printf >&2 "\n${CHIGH}Running ${testcase##*/} -> FAILED${CRESET}"
		else
			echo >&2 "${CHIGH}Running ${testcase##*/} -> FAILED${CRESET}"
		fi
	else
		PASS=$((PASS+1))
		if [ "$MSGLEVEL" -le 1 ]; then
			printf " "
		fi
	fi
	ALL=$((ALL+1))
	if [ "$MSGLEVEL" -le 1 ]; then
		:
	elif [ "$MSGLEVEL" -le 2 ]; then
		echo
	fi
done

echo >&2 "Statistics: $ALL tests were run: $PASS successfully and $FAIL failed"
if [ -n "$FAILED_TESTS" ]; then
	echo >&2 "Failed tests: $FAILED_TESTS"
else
	echo >&2 'All tests seem to have been run successfully. What could possibly go wrong?'
fi
# ensure we don't overflow
exit $((FAIL <= 255 ? FAIL : 255))