#!/bin/bash
#
# Run a scheduler for TIMEOUT seconds inside virtme-ng and catch potential
# errors, then unload the scheduler and return the exit status.

# Maximum time for each scheduler run.
TEST_TIMEOUT=30

# Maximum timeout for the guest used for each scheduler run (this is used to
# hard-shutdown the guest in case of system hangs).
GUEST_TIMEOUT=60

# List of schedulers to test
#
# TODO:
#   - scx_mitosis: not ready yet
#
declare -A SCHEDS

VNG_RW=''

# Enable vng rw for when on ci.
if [ $# -ge 3 ] ; then
  if [ "$3" == "VNG_RW=true" ]; then
    echo 'setting vng to mount rw'
    VNG_RW=' --rw '
  fi
fi

# enable running tests on individual schedulers
if [ $# -ge 2 ] ; then
    SCHEDS[$2]="-v"
else
    SCHEDS["scx_simple"]="-v"
    SCHEDS["scx_central"]="-v"
    SCHEDS["scx_nest"]="-v"
    SCHEDS["scx_flatcg"]="-v"
    SCHEDS["scx_pair"]="-v"
    SCHEDS["scx_rusty"]="-v"
    SCHEDS["scx_p2dq"]="-v"
    SCHEDS["scx_rustland"]="-v"
    SCHEDS["scx_bpfland"]="-v"
    SCHEDS["scx_layered"]="-v --run-example"
fi

if [[ -v SCHEDS["scx_layered"] ]] ; then
    SCHEDS["scx_layered"]="--run-example -v --stats 1"
fi

printf "testing scheds:\n"
for i in "${!SCHEDS[@]}"; do
    printf "%s=%s\n" "$i" "${SCHEDS[$i]}";
done

if [ ! -x `which vng` ]; then
    echo "vng not found, please install virtme-ng to enable testing"
    exit 1
fi
if [ $# -lt 1 ]; then
    echo "Usage: $0 VMLINUZ"
    exit 1
fi
kernel=$1

for sched in ${!SCHEDS[@]}; do
    args=${SCHEDS[$sched]}
    sched_path=$(find -type f -executable -name ${sched})
    if [ ! -n "${sched_path}" ]; then
        echo "${sched}: binary not found"
        echo "FAIL: ${sched}"
        exit 1
    fi
    echo "testing ${sched_path}"

    rm -f /tmp/output
    timeout --preserve-status ${GUEST_TIMEOUT} \
        vng --user root -m 10G --cpu 8 $VNG_RW -v -r ${kernel} -- \
            "timeout --foreground --preserve-status ${TEST_TIMEOUT} ${sched_path} ${args}" \
                2> >(tee /tmp/output) </dev/null
        grep -v " Speculative Return Stack Overflow" /tmp/output | \
            sed -n -e '/\bBUG:/q1' \
                   -e '/\bWARNING:/q1' \
                   -e '/\berror\b/Iq1' \
                   -e '/\bstall/Iq1' \
                   -e '/\btimeout\b/Iq1'
    res=$?
    if [ ${res} -ne 0 ]; then
        echo "FAIL: ${sched}"
        exit 1
    else
        echo "OK: ${sched}"
    fi
    cp /tmp/output test_log.ci.log
done
