#!/bin/bash

set -e
set -o pipefail

function on_exit() {
	# ding ding ding ding
	echo -ne '\007' ; sleep 0.1 ; echo -ne '\007' ; sleep 0.1 ; echo -ne '\007' ; sleep 0.1 ; echo -ne '\007' ; sleep 0.1 ;
}
trap on_exit EXIT

if [ ! -e "setup.py" ]; then
	echo "The script must be executed from within the repository's root directory."
	exit
fi

if [ -z "${SECRET_PEERINGDB_API_KEY}" ]; then
	echo "SECRET_PEERINGDB_API_KEY must be set, but it is not."
	exit
fi

export PYTHONPATH="`pwd`"
ROOT="`pwd`"

TESTS_DIR="tests"
LAST_RESULTS_DIR="$TESTS_DIR/last_results"

ALL_BGPSPEAKERS="bird1 bird2 bird3 openbgpd_portable"
BGPSPEAKERS="$ALL_BGPSPEAKERS"
LIVE_TEST_IDS="`find $TESTS_DIR/live_tests/scenarios/* -maxdepth 0 -type d | cut -d '/' -f 4`"

function join_last_results() {
	if [ ! -e $LAST_RESULTS_DIR/static.last ]; then
		echo "ERROR: static.last missing"
		exit 1
	fi
	cat $LAST_RESULTS_DIR/static.last > $TESTS_DIR/last

	if [ ! -e $LAST_RESULTS_DIR/extres.last ]; then
		echo "ERROR: extres.last missing"
		exit 1
	fi
	cat $LAST_RESULTS_DIR/extres.last >> $TESTS_DIR/last

	for bgpspeaker in $ALL_BGPSPEAKERS; do
		for d in $TESTS_DIR/live_tests/scenarios/*; do
			if [ -d $d ]; then
				if [[ `find $d/test_${bgpspeaker}*.py 2>/dev/null | wc -l` -gt 0 ]]; then
					TARGET_FILE="live_`basename $d`_${bgpspeaker}.last"
					if [ ! -e $LAST_RESULTS_DIR/$TARGET_FILE ]; then
						echo "ERROR: $TARGET_FILE missing"
						exit 1
					fi
					cat $LAST_RESULTS_DIR/$TARGET_FILE >> $TESTS_DIR/last
				fi
			fi
		done
	done

	num_of_tests="`cat $TESTS_DIR/last | egrep -v "^(Ran|OK|---|$)" | egrep "... PASSED$" | wc -l`"
	echo "{\"unique_test_cases\": ${num_of_tests}}" > $TESTS_DIR/last.json

	cd $ROOT
	./utils/build_integration_tests_docs.py > docs/SUPPORTED_SPEAKERS_CI.txt
	./utils/build_supported_speakers_table.py > docs/SUPPORTED_SPEAKERS_FEATURES.txt
	cd docs
	make html

	#rm $LAST_RESULTS_DIR/*.last
	#rmdir $LAST_RESULTS_DIR
}

function usage() {
	echo "$0 [ join_only | \"<list_of_test_ids>\" [ \"<list_of_bgp_speakers>\" ] ]"
	echo ""
	echo "Test IDs:"
	echo " - cli"
	echo " - static"
	echo " - build_only"
	echo " - extres"
	echo " - all"
	for id in $LIVE_TEST_IDS; do
		echo " - $id"
	done
	echo ""
	echo "BGP speakers:"
	for s in $ALL_BGPSPEAKERS; do
		echo " - $s"
	done
	exit 1
}

if [ "$1" == "join_only" ]; then
	join_last_results
	exit
fi

if [ -n "$2" ]; then
	for speaker in $2; do
		egrep "^(`tr ' ' '|' <<< $ALL_BGPSPEAKERS`)$" <<< "$speaker" &>/dev/null || { usage ; exit 1; }
	done
	BGPSPEAKERS="$2"
fi

if [ -d "$LAST_RESULTS_DIR" -a -z "$1" ]; then
	echo "Last results directory already existing: please check and then remove it - rmdir $LAST_RESULTS_DIR"
	exit
fi

echo "Pulling Docker images needed for the tests..."
# To be kept in sync with .github/workflows/cicd.yml
docker pull pierky/bird:1.6.8
docker pull pierky/bird:2.16
docker pull pierky/bird:3.0-alpha2
docker pull pierky/openbgpd:8.4
docker pull pierky/openbgpd:8.7
docker pull pierky/exabgp:4.2.7
docker pull nlnetlabs/routinator:v0.13.2

# Check for codetags
echo "Verifying codetags..."
set +e
egrep -r "#XXX|#FIXME|#BUG" pierky/ templates/ scripts/ config.d/ docs/ examples/
if [ $? -eq 0 ]; then
	echo "One ore more codetags found."
	exit
fi
set -e

# At first verify if templates and fingerprints are aligned.
echo "Verifying if templates and fingerprints are aligned..."
pytest -vs -x tests/static/test_cfg_program.py 2>&1

# Then check the code
echo "Checking code..."
flake8 pierky/ scripts/ 2>&1

echo "Verifying no Docker instances are running..."
if [ "`docker ps | grep -v "CONTAINER ID" | wc -l | awk '{print $1}'`" != "0" ]; then
	echo "One or more Docker instances are already running"
	exit
fi

# echo "Verifying no VMs are running..."
# if [ "`virsh list --name --state-running | wc -w`" != "0" ]; then
# 	echo "One or more VMs are already running"
# 	exit
# fi

if [ ! -d $LAST_RESULTS_DIR ]; then
	mkdir -p $LAST_RESULTS_DIR
fi

if [[ -z "$1" || `echo "$1" | grep  "\bcli\b"` ]]; then
	echo -n "Testing CLI commands... "
	./tests/cli 2>&1
fi

if [[ -z "$1" || `echo "$1" | grep  "\bstatic\b"` ]]; then
	echo "Running static tests..."
	pytest -vs -x $TESTS_DIR/static 2>&1 | tee $LAST_RESULTS_DIR/static.last
fi

if [[ -z "$1" || `echo "$1" | grep  "\bextres\b"` ]]; then
	echo "Running external resources tests..."
	pytest -vs -x $TESTS_DIR/external_resources 2>&1 | tee $LAST_RESULTS_DIR/extres.last
fi

if [[ -z "$1" || `echo "$1" | grep  "\bbuild_only\b"` ]]; then
	echo "Testing live scenarios with BUILD_ONLY=1..."
	BUILD_ONLY=1 pytest -vs -x $TESTS_DIR/live_tests/scenarios/*/test_*.py -k test_010_setup
fi

echo "Running live tests..."
for bgpspeaker in $BGPSPEAKERS; do
	for d in $TESTS_DIR/live_tests/scenarios/*; do
		if [ -d $d ]; then
			LIVE_TEST_NAME="`basename $d`"

			if [[ -z "$1" || "$1" == "all" || `echo "$1" | grep  "$LIVE_TEST_NAME"` ]]; then
				if [[ `find $d/test_${bgpspeaker}*.py 2>/dev/null | wc -l` -gt 0 ]]; then
					echo " - live test: $LIVE_TEST_NAME, $bgpspeaker"
					TARGET_FILE="live_${LIVE_TEST_NAME}_${bgpspeaker}.last"
					REUSE_KVM_INSTANCES=1 pytest -vs -x $d/test_${bgpspeaker}*.py 2>&1 | tee $LAST_RESULTS_DIR/$TARGET_FILE
				fi
			fi
		fi
	done
	if [ "${bgpspeaker}" == "openbgpd_latest" -o "${bgpspeaker}" == "openbgpd_previous" ]; then
		if [ `virsh list --name --state-running | egrep -v "^$" | wc -l` -gt 0 ]; then
			echo "Shutting down rs KVM instance..."
			./utils/run rs 'shutdown -p now'

			attempts=1
			vm_up=1
			while [[ $attempts -le 15 && $vm_up -eq 1 ]]
			do
				sleep 1

				set +e
				virsh list --name --state-running | egrep "^.+$" &>/dev/null
				if [ $? -ne 0 ]; then
					vm_up=0
				fi
				set -e

				attempts=`expr $attempts + 1`
			done
		fi
	fi
done

join_last_results
