#!/usr/bin/env bash
#
# Copyright IBM Corp. 2017
#
# Usage: test_run <testname> <cmdline>
#
# Announce a test case, run it, and record the resulting output in the
# test log file. Must be run after testsuite_init.
#

trap 'echo ; exit 1' SIGINT

[[ -z "$TOPDIR" ]] && TOPDIR=$(readlink -f $(dirname $0)/..) && test -d "$TOPDIR"

source "$TOPDIR/bin/common"
#echo $@

EXCERPTLEN=10
TESTNAME="$1"
shift
SCRIPT=$1
shift

OPTS=''
while [ $# -gt 0 ] ; do

    OPT=$1
    shift
    case $OPT in

        --script-args )
            OPTS="$OPTS $1"
            shift
            ;;

        --coverage )
            COVER_DB=$1
            export PERL_COVER_ARGS="-MDevel::Cover=-db,$(COVER_DB),-coverage,statement,branch,condition,subroutine,-silent,1"
            shift
            OPTS="$OPTS $OPT $COVER_DB --keep-going"
            ;;

        * )
            echo "Error: test_run: unexpected option '$OPT'"
            exit 1
            ;;

    esac
done

if [[ "$SCRIPT" =~ '.pl' ]] ; then
    INVOKE_COVER="perl ${PERL_COVER_ARGS}"
fi

TIME=$(type -P time 2>/dev/null)
if [ ! -z "$TIME" ] ; then
        TIME="$TIME -v -o $TIMEFILE"
        if ! $TIME true 2>/dev/null ; then
                TIME=""
        fi
fi

t_announce "$TESTNAME"

case "$OSTYPE" in
linux*)
    let POS=$(stat -c %s "$LOGFILE")+1
    ;;
*)
    let POS=$(stat -f %z "$LOGFILE")+1
    ;;
esac

t_detail "COMMAND" "\"$SCRIPT $OPTS*\"" >>"$LOGFILE"
t_detail "OUTPUT" "" >>"$LOGFILE"

# Run command
$TIME bash -c "$INVOKE_COVER $SCRIPT $OPTS" 2>&1 | t_indent >>"$LOGFILE"
RC=${PIPESTATUS[0]}

# Evaluate output of time command
ELAPSED=
RESIDENT=
SIGNAL=
if [ ! -z "$TIME" ] ; then
        while read LINE ; do
                case "$LINE" in
                "Command terminated by signal"*) SIGNAL=${LINE##* } ;;
                "Elapsed"*) ELAPSED=$(elapsed_to_ms ${LINE##* }) ;;
                "Maximum resident"*) RESIDENT=${LINE##* } ;;
                "Exit status"*) RC=${LINE##* } ;;
                esac
        done < "$TIMEFILE"
        rm -f "$TIMEFILE"
fi

# Save last output line as reason in case of skip result
LAST=$(tail -n 1 "$LOGFILE" | sed -e 's/^  //g')

t_detail "EXITCODE" "$RC" >>"$LOGFILE"

# Show result
if [ $RC -eq 0 -a -z "$SIGNAL" ] ; then
        RESULT="pass"
        t_pass "$TESTNAME"
else
        if [ $RC -eq 2 ] ; then
                RESULT="skip"
                t_skip "$TESTNAME"
        else
                if [ -z "$SIGNAL" ] ; then
                        RESULT="fail"
                        t_fail "$TESTNAME"
                else
                        RESULT="kill"
                        t_kill "$TESTNAME"
                fi
        fi
fi

if [ ! -z "$SIGNAL" ] ; then
        t_detail "SIGNAL" "$SIGNAL" >>"$LOGFILE"
fi

if [ ! -z "$ELAPSED" ] ; then
        echo -n " (time $(($ELAPSED/1000)).$(($ELAPSED%1000/100))s, "
        echo "elapsed $TESTNAME $ELAPSED" >> "$COUNTFILE"
fi

if [ ! -z "$RESIDENT" ] ; then
        echo -n "mem $(($RESIDENT/1024)).$((($RESIDENT%1024)/100))MB)"
        echo "resident $TESTNAME $RESIDENT" >> "$COUNTFILE"
fi

echo

# Show skip reason
if [ $RC -eq 2 ] ; then
        t_detail "REASON" "$LAST" | t_indent
        t_detail "REASON" "$LAST" >>"$LOGFILE"
fi

# Show log excerpt on failure or if requested
if [ $RC -ne 0 -a $RC -ne 2 -o "$V" == "1" ] ; then
        LEN=$(tail -c "+$POS" "$LOGFILE" | wc -l)
        if [ "$LEN" -gt "$EXCERPTLEN" -a "$V" != "1" ] ; then
                echo "    Skipping $LEN previous lines (see $LOGFILE)"
                echo "    ..."
                tail -c "+$POS" "$LOGFILE" | tail -n $EXCERPTLEN | t_indent
                let LEN=$LEN-$EXCERPTLEN
        else
                tail -c "+$POS" "$LOGFILE" | t_indent
        fi
fi

# Log more details
[ ! -z "$ELAPSED" ] && t_detail "TIME" "${ELAPSED}ms" >>"$LOGFILE"
[ ! -z "$RESIDENT" ] && t_detail "MEM" "${RESIDENT}kB" >>"$LOGFILE"
t_detail "RESULT" "$RESULT" >> "$LOGFILE"

exit $RC
