#!/bin/bash
#
# This script must be run as root.
#
# If testing for a particular event, add the expected event-result file under
# rtas_errd/tests/event-results and call the script with option :
#   "-t <path-to-event-file>".
# In that case only that event is tested, other options like -s and -e are
# not tested.

# Make sure only root can run our script as user has to be able to access
# servicelog database (/var/lib/servicelog/servicelog.db).
if [ $EUID -ne 0 ]; then
	echo "This script must be run as root!"
	exit 1
fi

RED='\e[0;31m'
GRN='\e[0;32m'
NC='\e[0m' # No Colour

hash servicelog servicelog_manage 2>/dev/null ||
{
	echo -n "Script require servicelog and servicelog_manage "
	echo    "but some of them are not installed. Aborting.";
	exit 1;
}

SERVICELOG=`hash -t servicelog`
SERVICELOG_MANAGE=`hash -t servicelog_manage`

SERVICELOG_DB="/var/lib/servicelog/servicelog.db"

TOP_LEVEL=`dirname $0`/../..
EVENTS=$TOP_LEVEL/rtas_errd/tests/events
EVENT_RESULTS=$TOP_LEVEL/rtas_errd/tests/event-results
RTAS_ERRD=$TOP_LEVEL/rtas_errd/rtas_errd

SCENARIOFILE=$TOP_LEVEL/rtas_errd/tests/scenariofile.in
SCENARIODUMP=$TOP_LEVEL/rtas_errd/tests/scenario.dump
OUTEPOWFILE=$TOP_LEVEL/rtas_errd/tests/epowfile.out
TMP_SCENARIOFILE=`mktemp`

function register_success {
	/bin/true
}

function register_fail {
	yes | mv ${SERVICELOG_DB}.bak $SERVICELOG_DB;
	rm $TMP_SCENARIOFILE
	exit ${1:-1};
}

function register_event_fail {
	echo "FAIL $CUR_TEST ";
	register_fail ${1:-1};
}

function truncate_events {
	# Clear all events
	yes yes | $SERVICELOG_MANAGE  --truncate events >/dev/null 2>&1

	# Retrieve logged event
	dump=$($SERVICELOG --dump)

	if [ ! -z "$dump" ]; then
		register_event_fail;
	fi
}

function diff_epow_output_file {
	diffy=`cat ${OUTEPOWFILE}`
	if [ $diffy -ne 0 ]; then
		echo -e "${RED}Generated epow file mismatches expected output!${NC}"
		register_fail;
	fi

	register_success;
}

function diff_with_result_without_timestamp {
	if [ ! -f $1 ]; then
		echo "File $1 not found"
		register_event_fail;
	fi

	diffy=$(diff -a -y --suppress-common-lines $1 <(echo "$2") |  cut  -d ' ' -f1,2)

	while read -r line || [[ -n "$line" ]]
	do
		name=$line
		# Number of Predictive CPU Failure will be different.
		if [[ -n "$name" ]] && [[ "$name" != "Log Timestamp:" ]] && [[ "$name" != "Event Timestamp:" ]] && [[ "$name" != "Update Timestamp:" ]] && [[ "$name" != "Platform:" ]] && [[ "$name" != "Node Name:" ]] && [[ "$name" != "Model/Serial:" ]] && [[ "$name" != "Predictive CPU" ]]
		then
			register_event_fail;
		fi
	done <<< "$diffy"

	register_success;
}

function log_event {
	if [ -x $RTAS_ERRD ]; then
		$RTAS_ERRD -d $1 >/dev/null 2>&1
	else
		echo "Fatal error, cannot execute binary '$RTAS_ERRD'. Did you make?";
		register_fail;
	fi

	R=$?
	if [ $R -ne 0 ]; then
		if [ -r $OUTEPOWFILE ]; then
			rm $OUTEPOWFILE
		fi
		register_event_fail $R;
	fi
}

function retrieve_and_compare_event {
	# Retrieve logged event
	output=$($SERVICELOG --dump 2>/dev/null)
	R=$?
	if [ $R -ne 0 ]; then
		register_event_fail $R;
	fi

	diff_with_result_without_timestamp $1 "$output"
	register_success
}

function usage {
        echo "Usage: $0 [-h] [-t <event_file>]" >&2;
        exit $1;
}

cp -a $SERVICELOG_DB ${SERVICELOG_DB}.bak
all_tests="$EVENTS/*"

while getopts ":t:h" opt; do
	option=$opt
	case "$opt" in
		t)
			if [ ! -r $OPTARG ]; then
				echo "The event file ($OPTARG) does not exist."
				exit 1;
			fi

			all_tests=$OPTARG
			;;
		h)
			usage 0
			;;
		*)
			usage 1
			;;
	esac
done

for the_test in $all_tests; do
	truncate_events

	CUR_TEST=$(basename $the_test)
	RESULT="$EVENT_RESULTS/$CUR_TEST.out"

	log_event "-f $the_test"
	R=$?
	if [[ $R -ne 0 ]] ; then
		echo -e "${RED}$the_test FAILED with RC $R${NC}"
		register_fail $R
	fi

	retrieve_and_compare_event ${RESULT}
	R=$?
	if [[ $R -ne 0 ]] ; then
		echo -e "${RED}$the_test FAILED with RC $R${NC}"
		register_fail $R
	fi
done

if [ -z $option ] ; then
	# Create temporary scenario file
	cp ${SCENARIOFILE} ${TMP_SCENARIOFILE}
	sed -i "s|^|$(dirname $0)\/|" ${TMP_SCENARIOFILE}

	#Check option s
	truncate_events
	CUR_TEST=$(basename ${SCENARIOFILE})
	log_event "-s ${TMP_SCENARIOFILE}"
        output=$($SERVICELOG --dump 2>/dev/null)
        R=$?
        if [ $R -ne 0 ]; then
                register_fail $R;
        fi

	retrieve_and_compare_event ${SCENARIODUMP} "$output"


	#Check output files
	truncate_events
	CUR_TEST=$(basename ${SCENARIOFILE})
	log_event "-s ${TMP_SCENARIOFILE} -e $OUTEPOWFILE"
	diff_epow_output_file
	rm $OUTEPOWFILE
	rm $TMP_SCENARIOFILE
fi

yes | mv ${SERVICELOG_DB}.bak $SERVICELOG_DB
echo -e "${GRN}PASS${NC}"
exit 0
