| #!/bin/bash |
| SHELL=/bin/bash |
| |
| THIS_SCRIPT_PATH=$(readlink -f $0) |
| THIS_DIR=$(dirname ${THIS_SCRIPT_PATH}) |
| REGRESSION_DIR="${THIS_DIR}/regression_test" |
| REG_LIB="${REGRESSION_DIR}/.library" |
| |
| source ${REG_LIB}/handle_exit.sh |
| source ${REG_LIB}/time_format.sh |
| source ${REG_LIB}/helper.sh |
| |
| export EXIT_NAME="$0" |
| |
| ############################################## |
| # grab the input args |
| INPUT=$@ |
| |
| TIMEOUT_EXEC="timeout" |
| TIME_EXEC=$($SHELL -c "which time") |
| VALGRIND_EXEC="valgrind --leak-check=full --max-stackframe=128000000 --error-exitcode=1 --track-origins=yes" |
| PERF_EXEC="perf stat record -a -d -d -d -o" |
| GDB_EXEC="gdb --args" |
| EXEC_PREFIX="" |
| |
| TEST_NAME="N/A" |
| LOG="" |
| LOG_FILE="" |
| FAILURE_FILE="" |
| |
| USE_TEMP_LOG="off" |
| RESTRICT_RESSOURCE="off" |
| TIME_LIMIT="86400s" #default to a full day |
| TOOL_SPECIFIED="off" |
| USE_TIMEOUT="on" |
| USE_TIME="on" |
| USE_LOGS="on" |
| COLORIZE_OUTPUT="off" |
| VERBOSE="0" |
| |
| function print_exit_type() { |
| CODE="$1" |
| if [[ $1 -ge 128 ]] |
| then |
| CODE="$(( $1 - 128 ))" |
| fi |
| |
| case $CODE in |
| 0) echo "NO_ERROR" |
| ;;1) echo "SIGHUP" |
| ;;2) echo "SIGINT" |
| ;;3) echo "SIGQUIT" |
| ;;4) echo "SIGILL" |
| ;;5) echo "SIGTRAP" |
| ;;6) echo "SIGABRT" |
| ;;7) echo "SIGBUS" |
| ;;8) echo "SIGFPE" |
| ;;9) echo "SIGKILL" |
| ;;10) echo "SIGUSR1" |
| ;;11) echo "SIGSEGV" |
| ;;12) echo "SIGUSR2" |
| ;;13) echo "SIGPIPE" |
| ;;14) echo "SIGALRM" |
| ;;15) echo "SIGTERM" |
| ;;16) echo "SIGSTKFLT" |
| ;;17) echo "SIGCHLD" |
| ;;18) echo "SIGCONT" |
| ;;19) echo "SIGSTOP" |
| ;;20) echo "SIGTSTP" |
| ;;21) echo "SIGTTIN" |
| ;;22) echo "SIGTTOU" |
| ;;23) echo "SIGURG" |
| ;;24) echo "SIGXCPU" |
| ;;25) echo "SIGXFSZ" |
| ;;26) echo "SIGVTALRM" |
| ;;27) echo "SIGPROF" |
| ;;28) echo "SIGWINCH" |
| ;;29) echo "SIGIO" |
| ;;30) echo "SIGPWR" |
| ;;31) echo "SIGSYS" |
| ;;124) echo "Timeout" |
| ;;127) echo "Errored" |
| ;;*) echo "${CODE}" |
| ;; |
| esac |
| } |
| |
| |
| function help() { |
| printf " |
| Called program with $[INPUT] |
| |
| Usage: ./exec_wrapper.sh [options] <path/to/arguments.file> |
| --tool [ gdb, valgrind, perf ] * run with one of the specified tool and only one |
| --log_file * output status to a log file |
| --test_name * label the test for pretty print |
| --failure_log * output the display label to a file if there was a failure |
| --time_limit * stops Odin after X seconds |
| --limit_ressource * limit ressource usage using ulimit -m (25% of hrdw memory) and nice value of 19 |
| --verbosity [0, 1, 2] * [0] no output, [1] output on error, [2] output the log to stdout |
| " |
| } |
| |
| function log_it { |
| INPUT="$@" |
| LOG="${LOG}${INPUT}" |
| } |
| |
| function dump_log { |
| #print to destination log if set |
| |
| if [ "_${LOG}" != "_" ] |
| then |
| if [ "${USE_LOGS}" == "on" ] |
| then |
| printf "${LOG}\n" >> ${LOG_FILE} |
| else |
| printf "${LOG}\n" |
| fi |
| |
| LOG="" |
| fi |
| |
| } |
| |
| #this hopefully will force to swap more |
| function restrict_ressource { |
| #some benchmark will eat all your ressource and OOM. setting a limit prevents this from happening, |
| # LUPEEG64 can use up to 36 Gb of Memory in total, We recommend growing your swap space |
| |
| PERCENT_LIMIT_FOR_LOW_RESSOURCE=20 |
| NICE_VALUE=19 |
| |
| MEMORY_SIZE=$(grep MemTotal /proc/meminfo |awk '{print $2}') |
| MEMORY_SIZE=$(( $(( $(( ${MEMORY_SIZE} )) * ${PERCENT_LIMIT_FOR_LOW_RESSOURCE} )) / 100 )) |
| |
| ulimit -m ${MEMORY_SIZE} |
| renice -n ${NICE_VALUE} -p $$ &> /dev/null |
| |
| log_it "Setting Nice value to ${NICE_VALUE}\n" |
| log_it "Virtual Memory Limit:\t$(ulimit -a | grep "virtual memory" | tr -s ' ' | cut -d ')' -f2)\n" |
| log_it "Physical Memory Limit:\t$(ulimit -a | grep "max memory size" | tr -s ' ' | cut -d ')' -f2)\n" |
| dump_log |
| } |
| |
| function pretty_print_status() { |
| |
| RESULT=$1 |
| line=$(printf '\040%.0s\056%.0s' {1..36}) |
| empty_line=$(printf '\040%.0s\040%.0s' {1..36}) |
| |
| if [ "_$RESULT" == "_" ] |
| then |
| printf " ${empty_line} ${TEST_NAME}\n" |
| elif [ "_${COLORIZE_OUTPUT}" == "_off" ] |
| then |
| printf " ${RESULT}${line:${#RESULT}} ${TEST_NAME}\n" |
| else |
| if [ "_$RESULT" == "_Ok" ] |
| then |
| printf " \033[0;32m${RESULT}${line:${#RESULT}}\033[0m ${TEST_NAME}\n" |
| else |
| printf " \033[0;31m${RESULT}${line:${#RESULT}}\033[0m ${TEST_NAME}\n" |
| fi |
| fi |
| } |
| function display() { |
| |
| CAUGHT_EXIT_CODE="$1" |
| LEAK_MESSAGE="" |
| |
| # check for valgrind leaks |
| LEAK_COUNT="$(cat ${LOG_FILE} | grep 'ERROR SUMMARY:' | awk '{print $4}' | grep -E '^\-?[0-9]+$')" |
| case "_${LEAK_COUNT}" in |
| _|_0) LEAK_MESSAGE="" |
| ;;_1) LEAK_MESSAGE="[${LEAK_COUNT}]Leak" |
| ;;*) LEAK_MESSAGE="[${LEAK_COUNT}]Leaks" |
| esac |
| |
| # check for uncaught errors |
| if [ "_${CAUGHT_EXIT_CODE}" == "_0" ] |
| then |
| ERROR_CATCH="$(cat ${LOG_FILE} | grep 'Program Exit Code:' | awk '{print $4}' | grep -E '^\-?[0-9]+$')" |
| [ "_${ERROR_CATCH}" != "_" ] && CAUGHT_EXIT_CODE="${ERROR_CATCH}" |
| fi |
| |
| # check for uncaught errors |
| if [ "_${CAUGHT_EXIT_CODE}" == "_0" ] |
| then |
| ERROR_CATCH="$(cat ${LOG_FILE} | grep 'Command terminated by signal:' | awk '{print $5}' | grep -E '^\-?[0-9]+$')" |
| [ "_${ERROR_CATCH}" != "_" ] && CAUGHT_EXIT_CODE="${ERROR_CATCH}" |
| fi |
| |
| EXIT_ERROR_TYPE=$( print_exit_type "${CAUGHT_EXIT_CODE}" ) |
| |
| |
| if [ "_${CAUGHT_EXIT_CODE}" == "_0" ] && [ "_${LEAK_MESSAGE}" == "_" ] |
| then |
| pretty_print_status "Ok" |
| else |
| pretty_print_status "Failed ${LEAK_MESSAGE} exit:$1 \"${EXIT_ERROR_TYPE}\"" |
| [ "_${FAILURE_FILE}" != "_" ] && echo "${TEST_NAME}" >> ${FAILURE_FILE} |
| fi |
| |
| } |
| |
| ######################################################### |
| # START HERE |
| |
| if [[ "$#" == 0 ]] |
| then |
| help |
| _exit_with_code "-1" |
| fi |
| |
| while [[ "$#" > 0 ]] |
| do |
| case $1 in |
| |
| --log_file) |
| LOG_FILE=$2 |
| shift |
| ;; |
| |
| --test_name) |
| TEST_NAME=$2 |
| export EXIT_NAME="${TEST_NAME}" |
| shift |
| ;; |
| |
| --failure_log) |
| FAILURE_FILE=$2 |
| shift |
| ;; |
| |
| --time_limit) |
| TIME_LIMIT=$2 |
| shift |
| ;; |
| |
| --limit_ressource) |
| RESTRICT_RESSOURCE="on" |
| ;; |
| |
| --verbosity) |
| case "_$2" in |
| _0) VERBOSE="0";; |
| _1) VERBOSE="1";; |
| _2) VERBOSE="2";; |
| *) |
| echo "verbosity level is invalid: $2" |
| help |
| _exit_with_code "-1" |
| ;; |
| esac |
| log_it "Using verbose output level ${VERBOSE}\n" |
| |
| shift |
| ;; |
| |
| --tool) |
| |
| if [ ${TOOL_SPECIFIED} == "on" ]; then |
| echo "can only run one tool at a time" |
| help |
| _exit_with_code "-1" |
| else |
| case $2 in |
| valgrind) |
| EXEC_PREFIX="${VALGRIND_EXEC} ${EXEC_PREFIX}" |
| ;; |
| gdb) |
| USE_TIMEOUT="off" |
| USE_LOGS="off" |
| EXEC_PREFIX="${GDB_EXEC} ${EXEC_PREFIX}" |
| ;; |
| perf) |
| EXEC_PREFIX="${PERF_EXEC} ${EXEC_PREFIX}" |
| shift |
| ;; |
| *) |
| echo "Invalid tool $2 passed in" |
| help |
| _exit_with_code "-1" |
| ;; |
| esac |
| TOOL_SPECIFIED="on" |
| shift |
| fi |
| ;; |
| *) |
| break |
| ;; |
| esac |
| shift |
| done |
| |
| ARG_FILE=$1 |
| |
| if [ "${RESTRICT_RESSOURCE}" == "on" ] |
| then |
| restrict_ressource |
| fi |
| |
| |
| if [[ -t 1 ]] && [[ -t 2 ]] && [[ ! -p /dev/stdout ]] && [[ ! -p /dev/stderr ]] |
| then |
| COLORIZE_OUTPUT="on" |
| log_it "Using colorized output\n" |
| fi |
| |
| if [ "${USE_LOGS}" == "on" ] |
| then |
| if [ "_${LOG_FILE}" == "_" ] |
| then |
| LOG_FILE=$(mktemp) |
| USE_TEMP_LOG="on" |
| log_it "using temporary logs\n" |
| elif [ -f ${LOG_FILE} ] |
| then |
| rm -f ${LOG_FILE} |
| log_it "removing old log file\n" |
| fi |
| |
| if [ ! -f ${LOG_FILE} ] |
| then |
| touch ${LOG_FILE} |
| log_it "creating new log file\n" |
| fi |
| fi |
| |
| if [ "${USE_TIME}" == "on" ] |
| then |
| EXEC_PREFIX="${TIME_EXEC} --output=${LOG_FILE} --append ${EXEC_PREFIX}" |
| log_it "running with /bin/time\n" |
| fi |
| |
| if [ "${USE_TIMEOUT}" == "on" ] |
| then |
| EXEC_PREFIX="timeout ${TIME_LIMIT} ${EXEC_PREFIX}" |
| log_it "running with timeout ${TIME_LIMIT}\n" |
| fi |
| dump_log |
| |
| pretty_print_status "" |
| |
| |
| _ARGS="" |
| EXIT_CODE="-1" |
| if [ "_${ARG_FILE}" == "_" ] || [ ! -f "${ARG_FILE}" ] |
| then |
| log_it "Must define a path to a valid argument file" |
| dump_log |
| else |
| _ARGS=$(cat ${ARG_FILE}) |
| if [ "${USE_LOGS}" == "on" ] |
| then |
| if [ "${VERBOSE}" == "2" ] |
| then |
| ${EXEC_PREFIX} ${_ARGS} 2>&1 | tee ${LOG_FILE} |
| else |
| ${EXEC_PREFIX} ${_ARGS} &>> ${LOG_FILE} |
| fi |
| else |
| ${EXEC_PREFIX} ${_ARGS} |
| fi |
| EXIT_CODE=$? |
| fi |
| |
| display "${EXIT_CODE}" |
| |
| EXIT_STATUS=0 |
| if [ "${EXIT_CODE}" != "0" ] |
| then |
| EXIT_STATUS=1 |
| fi |
| |
| if [ "${EXIT_STATUS}" != "0" ] && [ "${USE_LOGS}" == "on" ] && [ "${VERBOSE}" == "1" ] |
| then |
| cat ${LOG_FILE} |
| fi |
| |
| if [ ${USE_TEMP_LOG} == "on" ] |
| then |
| rm -f ${LOG_FILE} |
| fi |
| |
| exit ${EXIT_STATUS} |
| ### end here |