#!/usr/bin/bash -efu

# Called from standard-test-beakerlib to run beakerlib tests
# This script is copied to test-environment.

debug() {
    if [ -n "$DEBUG" ]; then
        echo "$*" >&2
    fi
}

msg_usage() {
    cat << EOF

Run beakerlib-libraries test.

Usage:
$PROG <options>

Options:
-h, --help              display this help and exit
-v, --verbose           turn on debug
-w, --workdir           test environment work dir
-a, --artifactsdir      test environment dir to store artifacts
-t, --test              test to run, can be a path to directory or a runtest.sh file
    --timeout           test timeout
EOF
}

# Entry

PROG="${PROG:-${0##*/}}"
DEBUG="${DEBUG:-}"
STR_DEBUG="${STR_DEBUG:-}"
STR_VERBOSE="${STR_VERBOSE:-}"
STR_BKR_TEST="${STR_BKR_TEST:-}"
STR_WORKDIR="${STR_WORKDIR:-}"
STR_ARTIFACTS_DIR="${STR_ARTIFACTS_DIR:-}"
STR_TIMEOUT="${STR_TIMEOUT:-0}"

# http://wiki.bash-hackers.org/howto/getopts_tutorial
opt=$(getopt -n "$0" --options "hvt:w:a:" --longoptions "help,verbose,test:,workdir:,artifactsdir:,timeout:" -- "$@")
eval set -- "$opt"
while [[ $# -gt 0 ]]; do
    case "$1" in
        -t|--test)
            export STR_BKR_TEST="$2"
            shift 2
            ;;
        -w|--workdir)
            STR_WORKDIR="$2"
            shift 2
            ;;
        -a|--artifactsdir)
            export STR_ARTIFACTS_DIR="$2"
            shift 2
            ;;
        --timeout)
            STR_TIMEOUT="$2"
            shift 2
            ;;
        -v|--verbose)
            DEBUG="-v"
            shift
            ;;
        -h|--help)
            msg_usage
            exit 0
            ;;
        --)
            shift
            ;;
        *)
            msg_usage
            exit 1
    esac
done

# Entry

if [ -z "$STR_BKR_TEST" ] || [ -z "$STR_WORKDIR" ] || [ -z "$STR_ARTIFACTS_DIR" ]; then
    echo "Use: $PROG -h for help."
    exit 0
fi

debug "Test: $STR_BKR_TEST"
debug "Work dir: $STR_WORKDIR"
debug "Artifacts dir: $STR_ARTIFACTS_DIR"
debug "Timeout: $STR_TIMEOUT"
STR_BKR_TEST_DASHED=$(echo "$STR_BKR_TEST" | sed -e 's/\//-/g')

# Up to this point any fail is considered as ci-sytem fail. Exit code != 0.
# Starting from this point and bellow any fail is considered as a test fail. Exit code == 0.

clean_exit() {
    rc=$?;
    trap - SIGINT SIGTERM SIGABRT EXIT # clear the trap
    echo "Run test $STR_BKR_TEST: done."
    # Close tee pipes
    for pid in $(ps -o pid --no-headers --ppid $$); do
        if [ -n "$(ps -p $pid -o pid=)" ]; then
            kill -s HUP $pid
        fi
    done
    # Check test result status
    local log_file_name="$STR_BKR_TEST_DASHED.log"
    local log_file_path="$STR_ARTIFACTS_DIR/$log_file_name"
    local status
    if [[ $rc -eq 127 ]]; then
        status="ERROR"
    elif [[ $rc -eq 124 ]]; then
        # test case timed out
        echo "$STR_BKR_TEST (test aborted due to timeout)" >&2
        status="ERROR"
    elif grep -q "RESULT: WARN" "$log_file_path"; then
        status="ERROR"
    elif grep -q "RESULT: FAIL" "$log_file_path"; then
        status="FAIL"
    elif grep -q "RESULT: PASS" "$log_file_path"; then
        status="PASS"
    elif grep -q "FAIL" "$log_file_path"; then
        status="FAIL"
    elif grep -q "PASS" "$log_file_path"; then
        status="PASS"
    else
        status="ERROR"
    fi
    echo "$status $STR_BKR_TEST" >> "$STR_ARTIFACTS_DIR/test.log"
    # Handle results.yml file, rename logs
    local results="$STR_ARTIFACTS_DIR/results.yml"
    local result=$(echo $status | tr '[:upper:]' '[:lower:]')
    test -f "$results" || echo 'results:' > "$results"
    printf '%s\n' '' \
        "- test: $STR_BKR_TEST" \
        "  result: $result"      \
        "  logs:"  \
        >> "$results"
    for log in "$log_file_path" "$logfile_stdout" "$logfile_stderr"; do
        if [ -f "$log" ]; then
            local prefixed_log="$STR_ARTIFACTS_DIR/${status}-$(basename $log)"
            mv -f "$log" "$prefixed_log"
            echo "  - $(basename $prefixed_log)" >> "$results"
        fi
    done
    # Exit code == 0, no matter of the test result.
    exit 0
}
trap clean_exit SIGINT SIGTERM SIGABRT EXIT

# For beakerlib-libraries
export PATH="$PATH:$STR_WORKDIR"
mkdir -p "$STR_ARTIFACTS_DIR"
logfile_stdout="$STR_ARTIFACTS_DIR/$STR_BKR_TEST_DASHED.log"
logfile_stderr="$STR_ARTIFACTS_DIR/$STR_BKR_TEST_DASHED-err.log"
# OUTPUTFILE has influence on beakerlib-libraries output
export OUTPUTFILE="$(realpath "$logfile_stdout")"
exec 3>&1 4>&2 1> >(tee -a "$logfile_stdout" >&3) 2> >(tee -a "$logfile_stderr" >&4)
mkdir -p "$STR_WORKDIR"
cd "$STR_WORKDIR"

if ! [ -d "$STR_BKR_TEST" ] && ! [ -f "$STR_BKR_TEST" ]; then
    # Next string goes to .log file
    echo "FAIL test $STR_BKR_TEST does not appear to be a file or directory"
    exit 127
fi

if [ -f "$STR_BKR_TEST" ]; then
    debug "Running test from file: $STR_BKR_TEST"
    cd $(dirname "$STR_BKR_TEST")
    timeout --foreground "$STR_TIMEOUT" /bin/sh -e ./$(basename "$STR_BKR_TEST")
    exit
fi

if [ -d "$STR_BKR_TEST" ]; then
    debug "Running test from directory: $STR_BKR_TEST"
    cd "$STR_BKR_TEST"
    # get-test-deps - is part of beakerlib-libraries
    get-test-deps -i .
    if [ -f "Makefile" ] && command -p -v "make" >"/dev/null" 2>&1; then
        debug "Running test from Makefile"
        timeout --foreground "$STR_TIMEOUT" make run
    elif [ -f "runtest.sh" ]; then
        debug "Running test from runtest.sh"
        timeout --foreground "$STR_TIMEOUT" /bin/sh -e ./runtest.sh
    else
        echo "FAIL test $STR_BKR_TEST do not know how to run test"
    fi
    exit
fi
