#!/bin/sh
# OpenAMQ tests script
# Copyright (c) 2004-2005 JPMorgan and iMatix Corporation
#
# See: readme.txt
#


# Script version
version="0.0a5"
# Verbose switch
verbose=0
# Global error status
error=0
# Time to wait for server to initialize/shutdown
updown=5
# Time limit for the timeout feature
timelimit=300

# Abort a test after the time limit has elapsed
timeout() 
{
    sleep $timelimit
    echo "Timeout expired..."
    echo 1 > AMQPTEST_TIMEOUT
    kill $1
}

# Try to do some clean-up
cleanup()
{
    # Shut down the daemon
    if test -f $DPATH/../tests/AMQPTEST_DPID; then
        dpid=$(cat $DPATH/../tests/AMQPTEST_DPID)
        kill $dpid
        wait $dpid
        if test "$1" = "timeout"; then
            echo "Respawning server..."
            startdaemon
        fi
    fi
    if test "$1" = "user"; then
        if test -f AMQPTEST_KPID; then
            kill $(cat AMQPTEST_KPID)
            rm -f AMQPTEST_KPID
        fi
        rm -f AMQPTEST_DPID
        echo ""
        echo "Tests interrupted by user"
        exit 0
    fi
    if test "$1" = "bye"; then
        rm -f AMQPTEST_DPID
        echo ""
        echo "Finished testing"
        exit 0
    fi
}


# Print to console the head and tail from the generated output
hint() 
{
    h=$(($2 / 2))
    if test $h -gt 5; then
        h=5
    fi
    if test $h -gt 0; then
        head -n $h $1 > AMQPTEST_HEAD
        tail -n $h $1 > AMQPTEST_TAIL
        if cmp -s AMQPTEST_HEAD AMQPTEST_TAIL; then
            cat AMQPTEST_HEAD
        else    
            cat AMQPTEST_HEAD
            echo "..."
            cat AMQPTEST_TAIL
        fi
        rm -f AMQPTEST_HEAD
        rm -f AMQPTEST_TAIL
    else
        cat $1    
    fi
}


# Handle a failure
fail() 
{
    echo "[FAIL] $1"
    if test "$verbose" = "1"; then
        hint $2 $(wc -l $2)
    fi
}


# Handle a pass
pass() 
{
    echo "[PASS] $1"
    if test "$verbose" = "1"; then
        hint $2 $(wc -l $2)
    fi
}


# Run a script
runscript() 
{
    echo "[TEST] $a_test"
    env PATH="$PATH:$IBASE/bin" sh $1 >$2 2>&1
    status=$?
    if test "$status" != "0"; then
        echo 1 > AMQPTEST_FAIL
    fi    
}


# Run a test script
runtest()
{
    # Run a test
    fail=0
    OUTPUT="$1.out"
    runscript $1 $OUTPUT &
    pid=$!
    # Handle timeout
    timeout $pid &
    killer=$!
    echo "$killer" >> AMQPTEST_KPID
    wait $pid
    if test -f AMQPTEST_FAIL; then
        fail=1
    fi
    if test -f AMQPTEST_TIMEOUT; then
        wait $killer
    else
        disown $killer
        kill $killer
    fi    
    # Check result
    if test -f AMQPTEST_TIMEOUT; then
        # Respawn server
        CPATH=$(pwd)
        cleanup "timeout"
        cd $CPATH
        # Handle timeout
        error=1
        fail $1 $OUTPUT
        echo "FAIL: TIMEOUT" >> $OUTPUT 
        mv "$OUTPUT" "$1.timeout"
    elif test -f core; then
        error=1
        fail $1 $OUTPUT
        echo "FAIL: CORE" >> $OUTPUT 
        mv core "$1.core"
        mv "$OUTPUT" "$1.fail"
    elif test ! -f "$1.ok"; then
        if test "$fail" = "0"; then
            pass $1 $OUTPUT
        else
            error=1
            fail $1 $OUTPUT
            echo "FAIL: EXIT STATUS" >> $OUTPUT 
            mv "$OUTPUT" "$1.fail"
        fi
    elif cmp -s "$OUTPUT" "$1.ok"; then
        pass $1 $OUTPUT
    else
        error=1
        fail $1 $OUTPUT
        echo "FAIL: UNEXPECTED RESULTS" >> $OUTPUT 
        mv "$OUTPUT" "$1.fail"
    fi
}


# Run a test set
testset()
{
    rm -f AMQPTEST_TIMEOUT
    rm -f AMQPTEST_FAIL
    for a_test in test_*.sh; do
        if test "$a_test" != "test_*.sh"; then 
            echo ""
            runtest "$a_test"
            rm -f AMQPTEST_TIMEOUT
            rm -f AMQPTEST_FAIL
        else
            if test tests_* = "tests_*"; then 
                echo ""
                echo "(WW) Nothing to do for $1" 
            fi
        fi
    done
    rm -f AMQPTEST_KPID
}

# AMQP daemon starter
startdaemon()
{
    if ps -A | grep openamqd; then
        echo "OpenAMQ daemon found running"
        echo "WARNING: The script will not manage shutting down the daemon"
    else 
        echo "Starting the OpenAMQ daemon..."
        if test "$DPATH" = ""; then cd ../servers; else cd $DPATH; fi
        export DPATH="$(pwd)"
        ./openamqd -q & 
        dpid=$!
        cd $DPATH/../tests
        echo $dpid > AMQPTEST_DPID
        echo "Sleeping $updown seconds ..."
        sleep $updown
    fi
    if ps -A | grep openamqd; then
        :
    else
        echo "Could not start the OpenAMQ daemon!"
        exit 1
    fi
}

# Trap Control-c
trap "cleanup user" SIGINT

# Check arguments
if test "$1" = "-h"; then 
    echo "OpenAMQP tester $version"
    echo ""
    echo "Copyright (c) 2004-2005 JPMorgan"
    echo "This is free software; see the source for copying conditions.  There is NO"
    echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
    echo ""
    echo "Provisional syntax: run_tests [options...]"
    echo "Options:"
    echo  "  -h               Show summary of command-line options"
    echo  "  verbose|quiet    Print to console the head and tail from test output (default = quiet)"
    echo  "  timeout          The number of seconds to wait before a timeout failure triggers (default = 300)"
    echo ""      
    echo "The order of arguments IS important (provisionally). Switches and filenames" 
    echo "are case sensitive."
    exit 0
else
    if test "$1" = "verbose"; then 
        verbose=1 
    fi    
    if test "$2" != ""; then 
        timelimit=$2 
    fi
fi    

echo ""
echo "OpenAMQ tester $version"
echo ""

# Start the daemon
startdaemon

# Run all test sets
for test_dir in tests_*; do
    if test "$test_dir" != "tests_*"; then 
        echo ""
        echo "(>>) Entering $test_dir directory..."
        cd $test_dir
        if test -f $test_dir; then
            sh $test_dir
        fi    
        if test ! -f $test_dir -o "$?" = "0"; then
            testset $test_dir
            for test_subdir in tests_*; do
                if test "$test_subdir" != "tests_*"; then 
                    echo ""
                    echo "  (>>) Entering $test_subdir subdirectory..."
                    cd $test_subdir
                    if test -f $test_subdir; then
                        sh $test_subdir
                    fi    
                    if test ! -f $test_subdir -o "$?" = "0"; then
                        testset $test_subdir
                    else    
                       echo "  (WW) Skiping test subset $test_subdir" 
                    fi
                    cd ..
                    echo ""
                    echo "  (<<) Leaving $test_subdir directory"
                fi
            done
        else
            echo "(WW) Skiping test set $test_dir" 
        fi
        cd ..
        echo ""
        echo "(<<) Leaving $test_dir directory"
    fi
done

# Stop the daemon
if test -f AMQPTEST_DPID; then
    echo ""
    echo "Stoping the OpenAMQ daemon..."
    cleanup
fi

# Result
exit $error
