#!/bin/bash

# Main pounder control script.

# Copyright (C) 2003-2006 IBM
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.

source libpounder.sh

# This function kills off pounder and related subprocesses.
function dokill() {
	echo "Killing off pounder(s)..."
	kill -INT `cat $POUNDER_PIDFILE`;
	rm -rf $POUNDER_PIDFILE
	#killall -9 randasys 2> /dev/null	# These run as user 'daemon' and have to be killed manually.
}

# Main function follows

function help() {
	cat << ENDL
Usage: ./pounder [-g logdir] [-x] [-d duration] [-n ipaddr] [-m max_failures] [-f] [-h|-u|-r|-k|-l|-e subtests|-i subtests|-c scheduler] [-s]

-h      	Brings up this menu
-c scheduler	Creates a new test scheduler called scheduler-tests.tar.gz in the pounder/schedulers folder.
		All subtests to be packaged with this scheduler must first be placed in the pounder/tests folder.
-x      	Enable X stress tests.
-d duration	Run pounder for duration seconds.
-n ipaddr	Use ipaddr for NFS tests.
-f		Remove pounder pid file before running.
-u      	Unmount NFS log storage.
-r      	Remount NFS log storage.
-g logdir      	Use logdir as the log directory. (You probably want -s too.)
-s      	Store logs locally.
-l      	List (both included and excluded) subtests that came with the test scheduler
-e subtests     Exclude subtests from next pounder run
-i subtests     Include previously excluded subtests in the next pounder run
-k      	Kill pounder.

run "./pounder" to run all subtests
run "./pounder subtest" to run just one particular subtest
        (example: ./pounder tests/T90ramp/D02build_kernel)
ENDL
}

function exclude() {
	echo "excluding from tests $@..."

	POUNDER_TESTS=$POUNDER_HOME/tests
	SUBTESTS_INC=`find $POUNDER_TESTS -name excluded -prune -o -type f -print -o -type l -print`

	for i in $@
	do
		BASENAME=`basename "$i"`

		ORIG_DIR=`pwd`
		cd `dirname $i`
		FULL_PATH=`pwd`/"$BASENAME"
		cd $ORIG_DIR

		FOUND=`echo "$SUBTESTS_INC" | grep -x "$FULL_PATH"`

		if [ -n "$FOUND" -a -x "$i" ]; then

			ALREADY_EXCLUDED=`grep -w "$BASENAME" $POUNDER_TESTS/excluded/testlist | cut -d " " -f1`
			if [ $ALREADY_EXCLUDED ]; then
				echo $ALREADY_EXCLUDED
				echo "$BASENAME has already been excluded from the test scheduler. Make sure the test names in the test scheduler are unique."
				exit 1
			fi

			echo "$BASENAME" "$FULL_PATH" >> "$POUNDER_TESTS"/excluded/testlist
			mv "$i" "$POUNDER_TESTS"/excluded/"$BASENAME"

			if [ $? -eq 0 ]; then
				echo "Successfully removed $i from test scheduler."
			else
				echo "Removal of $i from tests UNSUCCESSFUL."
			fi
		else
			echo "$i is not a subtest included in the current scheduler. Use ./pounder -l for list of valid, excludable subtests."
		fi
	done
}

function include() {
	echo "including in tests $@..."

        POUNDER_EXCLUDED=$POUNDER_HOME/tests/excluded

        for i in $@
        do
		ORIG_FILE=`grep -w "$i" $POUNDER_EXCLUDED/testlist | cut -d " " -f2`

		if [ -n "$ORIG_FILE" ]; then
			mv $POUNDER_EXCLUDED/$i $ORIG_FILE
			if [ $? -eq 0 ]; then
				sed "/$i /d" $POUNDER_EXCLUDED/testlist > $POUNDER_EXCLUDED/tempfile
				mv $POUNDER_EXCLUDED/tempfile $POUNDER_EXCLUDED/testlist
				echo "Successfully added $i back to test scheduler."
			else
				echo "Addition of $i to tests UNSUCCESSFUL."
			fi
		else
			echo "$i is not an excluded subtest. It may already be included in the current scheduler. Use ./pounder -l for list of valid, includable subtests."
		fi
        done
}

function list_tests() {

	if [ ! -d $POUNDER_HOME/tests ]; then
		echo "Error: No test schedule found. Did you run make install?"
		exit 1
	fi

	echo "Included subtests:"
	INCLUDED_TESTS=`find $POUNDER_HOME/tests -name excluded -prune -o -type f -print -o -type l -print`
	if [ -z "$INCLUDED_TESTS" ]; then
		echo "[NONE]"
	else
		echo "$INCLUDED_TESTS"
	fi
	echo

	echo "Excluded subtests:"

	if [ ! -d $POUNDER_HOME/tests/excluded ]; then
		echo "Error: $POUNDER_HOME/tests/excluded folder does not exist. Make sure your test scheduler was created or unpackaged correctly. Did you run make install?"
		exit 1
	fi

	EXCLUDED_TESTS=`grep -v "#" $POUNDER_HOME/tests/excluded/testlist`
	if [ -z "$EXCLUDED_TESTS" ]; then
		echo "[NONE]"
	else
		echo "$EXCLUDED_TESTS" | cut -d " " -f1
	fi

}

function create_scheduler() {
	TESTS_EXCLUDED=$POUNDER_HOME/tests/excluded
	REPO_EXCLUDED=$POUNDER_HOME/test_repo/excluded

	if [ ! -d $TESTS_EXCLUDED ]; then
		cp -r $REPO_EXCLUDED $TESTS_EXCLUDED
	elif [ ! -e $TESTS_EXCLUDED/testlist ]; then
		cp $REPO_EXCLUDED/testlist $TESTS_EXCLUDED/testlist
	fi

	tar -czf $POUNDER_HOME/schedulers/$@-tests.tar.gz tests
}
# process options: -x to run in xterms, -k to kill tests, -d to set duration,
# -f to remove bogus pounder.pid files.
while getopts d:kn:g:xure:i:m:c:shl? o
do
	case "$o" in
	   d) export DURATION="$OPTARG";;
	   k) dokill; exit;;
	   n) export NFS_SERVER="$OPTARG";;
	   g) export POUNDER_LOGDIR="$OPTARG";;
	   x) export DO_X_TESTS=1;;
	   f) rm -rf "$POUNDER_PIDFILE";;
	   u) umount $POUNDER_HOME/log 2> /dev/null; exit 0;;
	   s) export NFS_LOGGING=0;;
	   r) ./nfs_logging; exit;;
	   e) exclude $OPTARG; exit;;
	   i) include $OPTARG; exit;;
	   l) list_tests; exit;;
	   m) export MAX_FAILURES="$OPTARG";;
	   c) create_scheduler $OPTARG; exit;;
	   h) help $0; exit;;
	   '?') help $0; exit 1;;
	esac
done

# Did user ask for X tests when DISPLAY is set?
# Probably _not_ what the user wants.
if [ $DO_X_TESTS -eq 1 ] && [ ! -z "$DISPLAY" ]; then
	echo "WARNING: X tests are enabled and DISPLAY is set.  xterms will appear on this desktop!"
	echo "WARNING: Kill pounder NOW if this is not what you intended."
fi

# Get set up to read arguments, even though there aren't any...
shift `expr $OPTIND - 1`

# Are we already running?
if [ -f "$POUNDER_PIDFILE" ]; then
	echo "File $POUNDER_PIDFILE exists; pounder may already be running."
	echo "Either run 'pounder -k' to stop all tests, or remove it."
	exit 1
fi

# Did the user run Install?
if [ ! -x run-helper -o ! -x timed_loop -o ! -x infinite_loop ]; then
	echo "Could not find run-helper, infinite_loop or timed_loop.  Did you run Install?"
	exit -1
fi

# Try to mount NFS log store.
if [ -z "$NFS_LOGSERVER" -o -z "$NFS_LOGDIR" ]; then
	echo "NFS logging disabled because NFS_LOGSERVER or NFS_LOGDIR are not set."
	export NFS_LOGGING=0
else
	if [ $NFS_LOGGING -gt 0 ]; then
		./nfs_logging
	fi
fi

# Set up log directory
mkdir -p "$POUNDER_LOGDIR" 2> /dev/null
if [ ! -d "$POUNDER_LOGDIR" ]; then
	echo "Could not create $POUNDER_LOGDIR; aborting."
	exit 1
fi

# Set up dir for optional components
mkdir -p "$POUNDER_OPTDIR"
if [ ! -d "$POUNDER_OPTDIR" ]; then
	echo "Could not create $POUNDER_OPTDIR; aborting."
	exit 1
fi

# Set up tmpdir
mkdir -p "$POUNDER_TMPDIR"
if [ ! -d "$POUNDER_TMPDIR" ]; then
	echo "Could not create $POUNDER_TMPDIR; aborting."
	exit 1
fi

TEST_HEAD="$1"
if [ -z $TEST_HEAD ]; then
	TEST_HEAD=tests
fi

# needs to be a separate check in case there is no tests/ dir...
if [ ! -d "$TEST_HEAD" -a ! -f "$TEST_HEAD" ]; then
	echo "$TEST_HEAD does not exist!"
	exit 1
fi


# Dump environment variables...
export > "$POUNDER_LOGDIR/environment"

echo "Starting $POUNDER_VERSION"
echo "STARTING TESTS."
echo "To kill all tests, run 'pounder -k' or press ^C."

# Handle the duration thing...
function kill_after {
	sleep $DURATION
	./pounder -k
}
if [ ! -z "$DURATION" -a "$DURATION" -gt 0 ]; then
	kill_after &
fi

# Now run the tests
./run-helper $TEST_HEAD --leader