#!/bin/bash # # return values of this script are: # 0 success # 128 a test failed # >0 the number of timed-out tests # 255 parsing of parameters failed set -e if [ -f /proc/cpuinfo ] then MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) else MAKE_JOBS=8 fi ret=0 TEST_CFLAGS="" _help() { cat << EOF Usage options for $(basename $0) [--with-cc=arg [other options]] Executing this script without any parameter will only run the default configuration that has automatically been determined for the architecture you're running. --with-cc=* The compiler(s) to use for the tests This is an option that will be iterated. --test-vs-mtest=* Run test vs. mtest for '*' operations. Only the first of each options will be taken into account. To be able to specify options a compiler has to be given with the option --with-cc=compilername All other options will be tested with all MP_xBIT configurations. --with-{m64,m32,mx32} The architecture(s) to build and test for, e.g. --with-mx32. This is an option that will be iterated, multiple selections are possible. The mx32 architecture is not supported by clang and will not be executed. --cflags=* Give an option to the compiler, e.g. --cflags=-g This is an option that will always be passed as parameter to CC. --make-option=* Give an option to make, e.g. --make-option="-f makefile.shared" This is an option that will always be passed as parameter to make. --with-low-mp Also build&run tests with -DMP_{8,16,32}BIT. --mtest-real-rand Use real random data when running mtest. --with-valgrind --with-valgrind=* Run in valgrind (slow!). --limit-valgrind Run with valgrind on CI only on specific branches. --valgrind-options Additional Valgrind options Some of the options like e.g.: --track-origins=yes add a lot of extra runtime and may trigger the 30 minutes timeout. Godmode: --all Choose all architectures and gcc and clang as compilers but does not run valgrind. --format Runs the various source-code formatters and generators and checks if the sources are clean. -h --help This message -v --version Prints the version. It is just the number of git commits to this file, no deeper meaning attached EOF exit 0 } _die() { echo "error $2 while $1" if [ "$2" != "124" ] then exit 128 else echo "assuming timeout while running test - continue" local _tail="" which tail >/dev/null && _tail="tail -n 1 test_${suffix}.log" && \ echo "last line of test_"${suffix}".log was:" && $_tail && echo "" ret=$(( $ret + 1 )) fi } _make() { echo -ne " Compile $1 $2" suffix=$(echo ${1}${2} | tr ' ' '_') CC="$1" CFLAGS="$2 $TEST_CFLAGS" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log errcnt=$(wc -l < gcc_errors_${suffix}.log) if [[ ${errcnt} -gt 1 ]]; then echo " failed" cat gcc_errors_${suffix}.log exit 128 fi } _runtest() { make clean > /dev/null local _timeout="" which timeout >/dev/null && _timeout="timeout --foreground 90" if [[ "$MAKE_OPTIONS" =~ "tune" ]] then # "make tune" will run "tune_it.sh" automatically, hence "autotune", but it cannot # get switched off without some effort, so we just let it run twice for testing purposes echo -e "\rRun autotune $1 $2" _make "$1" "$2" "" $_timeout $TUNE_CMD > test_${suffix}.log || _die "running autotune" $? else _make "$1" "$2" "test" echo -e "\rRun test $1 $2" $_timeout ./test > test_${suffix}.log || _die "running tests" $? fi } # This is not much more of a C&P of _runtest with a different timeout # and the additional valgrind call. # TODO: merge _runvalgrind() { make clean > /dev/null local _timeout="" # 30 minutes? Yes. Had it at 20 minutes and the Valgrind run needed over 25 minutes. # A bit too close for comfort. which timeout >/dev/null && _timeout="timeout --foreground 1800" echo "MAKE_OPTIONS = \"$MAKE_OPTIONS\"" if [[ "$MAKE_OPTIONS" =~ "tune" ]] then echo "autotune branch" _make "$1" "$2" "" # The shell used for /bin/sh is DASH 0.5.7-4ubuntu1 on the author's machine which fails valgrind, so # we just run on instance of etc/tune with the same options as in etc/tune_it.sh echo -e "\rRun etc/tune $1 $2 once inside valgrind" $_timeout $VALGRIND_BIN $VALGRIND_OPTS $TUNE_CMD > test_${suffix}.log || _die "running etc/tune" $? else _make "$1" "$2" "test" echo -e "\rRun test $1 $2 inside valgrind" $_timeout $VALGRIND_BIN $VALGRIND_OPTS ./test > test_${suffix}.log || _die "running tests" $? fi } _banner() { echo "uname="$(uname -a) [[ "$#" != "0" ]] && (echo $1=$($1 -dumpversion)) || true } _exit() { if [ "$ret" == "0" ] then echo "Tests successful" else echo "$ret tests timed out" fi exit $ret } ARCHFLAGS="" COMPILERS="" CFLAGS="" WITH_LOW_MP="" TEST_VS_MTEST="" MTEST_RAND="" # timed with an AMD A8-6600K # 25 minutes #VALGRIND_OPTS=" --track-origins=yes --leak-check=full --show-leak-kinds=all --error-exitcode=1 " # 9 minutes (14 minutes with --test-vs-mtest=333333 --mtest-real-rand) VALGRIND_OPTS=" --leak-check=full --show-leak-kinds=all --error-exitcode=1 " #VALGRIND_OPTS="" VALGRIND_BIN="" CHECK_FORMAT="" CHECK_SYMBOLS="" C89="" C89_C99_ROUNDTRIP="" TUNE_CMD="./etc/tune -t -r 10 -L 3" alive_pid=0 function kill_alive() { disown $alive_pid || true kill $alive_pid 2>/dev/null } function start_alive_printing() { [ "$alive_pid" == "0" ] || return 0; for i in `seq 1 10` ; do sleep 300 && echo "Tests still in Progress..."; done & alive_pid=$! trap kill_alive EXIT } while [ $# -gt 0 ]; do case $1 in "--with-m64" | "--with-m32" | "--with-mx32") ARCHFLAGS="$ARCHFLAGS ${1:6}" ;; --c89) C89="1" ;; --c89-c99-roundtrip) C89_C99_ROUNDTRIP="1" ;; --with-cc=*) COMPILERS="$COMPILERS ${1#*=}" ;; --cflags=*) CFLAGS="$CFLAGS ${1#*=}" ;; --valgrind-options=*) VALGRIND_OPTS="$VALGRIND_OPTS ${1#*=}" ;; --with-valgrind*) if [[ ${1#*d} != "" ]] then VALGRIND_BIN="${1#*=}" else VALGRIND_BIN="valgrind" fi start_alive_printing ;; --limit-valgrind*) if [[ ("$GITHUB_BASE_REF" == "develop" && "$PR_NUMBER" == "") || "$GITHUB_REF_NAME" == *"valgrind"* || "$COMMIT_MESSAGE" == *"valgrind"* ]] then if [[ ${1#*d} != "" ]] then VALGRIND_BIN="${1#*=}" else VALGRIND_BIN="valgrind" fi start_alive_printing fi ;; --make-option=*) MAKE_OPTIONS="$MAKE_OPTIONS ${1#*=}" ;; --with-low-mp) WITH_LOW_MP="1" ;; --test-vs-mtest=*) TEST_VS_MTEST="${1#*=}" if ! [ "$TEST_VS_MTEST" -eq "$TEST_VS_MTEST" ] 2> /dev/null then echo "--test-vs-mtest Parameter has to be int" exit 255 fi start_alive_printing ;; --mtest-real-rand) MTEST_RAND="-DLTM_MTEST_REAL_RAND" ;; --format) CHECK_FORMAT="1" ;; --symbols) CHECK_SYMBOLS="1" ;; --all) COMPILERS="gcc clang" ARCHFLAGS="-m64 -m32 -mx32" ;; --help | -h) _help ;; --version | -v) echo $(git rev-list HEAD --count -- testme.sh) || echo "Unknown. Please run in original libtommath git repository." exit 0 ;; *) echo "Ignoring option ${1}" ;; esac shift done function _check_git() { git update-index --refresh >/dev/null || true git diff-index --quiet HEAD -- . || ( echo "FAILURE: $*" && exit 1 ) } [[ "$C89" == "1" ]] && make c89 if [[ "$C89_C99_ROUNDTRIP" == "1" ]] then make c89 make c99 _check_git "make c89; make c99" exit $? fi if [[ "$CHECK_SYMBOLS" == "1" ]] then make -f makefile.shared cat << EOF The following list shows the discrepancy between the shared library and the Windows dynamic library. To fix this error, one of the following things has to be done: * the script which generates tommath.def has to be modified (function generate_def() in helper.pl). * The exported symbols are really different for some reason This has to be manually investigated. EOF exit $(comm -3 <(nm -D --defined-only .libs/libtommath.so | cut -d' ' -f3 | grep -v '^_' | sort) <(tail -n+9 tommath.def | tr -d ' ' | sort) | tee /dev/tty | wc -l) fi if [[ "$CHECK_FORMAT" == "1" ]] then make astyle _check_git "make astyle" perl helper.pl --update-files _check_git "helper.pl --update-files" perl helper.pl --check-all _check_git "helper.pl --check-all" exit $? fi [[ "$VALGRIND_BIN" == "" ]] && VALGRIND_OPTS="" # default to CC environment variable if no compiler is defined but some other options if [[ "$COMPILERS" == "" ]] && [[ "$ARCHFLAGS$MAKE_OPTIONS$CFLAGS" != "" ]] then COMPILERS="${CC:-cc}" # default to CC environment variable and run only default config if no option is given elif [[ "$COMPILERS" == "" ]] then _banner "$CC" if [[ "$VALGRIND_BIN" != "" ]] then _runvalgrind "$CC" "" else _runtest "$CC" "" fi _exit fi archflags=( $ARCHFLAGS ) compilers=( $COMPILERS ) # choosing a compiler without specifying an architecture will use the default architecture if [ "${#archflags[@]}" == "0" ] then archflags[0]=" " fi _banner if [[ "$TEST_VS_MTEST" != "" ]] then make clean > /dev/null _make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent" echo _make "gcc" "$MTEST_RAND" "mtest" echo echo "Run test vs. mtest for $TEST_VS_MTEST iterations" _timeout="" which timeout >/dev/null && _timeout="timeout --foreground 1800" $_timeout ./mtest/mtest $TEST_VS_MTEST | $VALGRIND_BIN $VALGRIND_OPTS ./mtest_opponent > valgrind_test.log 2> test_vs_mtest_err.log retval=$? head -n 5 valgrind_test.log tail -n 2 valgrind_test.log exit $retval fi for i in "${compilers[@]}" do if [ -z "$(which $i)" ] then echo "Skipped compiler $i, file not found" continue fi compiler_version=$(echo "$i="$($i -dumpversion)) if [ "$compiler_version" == "clang=4.2.1" ] then # one of my versions of clang complains about some stuff in stdio.h and stdarg.h ... TEST_CFLAGS="-Wno-typedef-redefinition" else TEST_CFLAGS="" fi echo $compiler_version for a in "${archflags[@]}" do if [[ $(expr "$i" : "clang") -ne 0 && "$a" == "-mx32" ]] then echo "clang -mx32 tests skipped" continue fi if [[ "$VALGRIND_BIN" != "" ]] then _runvalgrind "$i" "$a $CFLAGS" [ "$WITH_LOW_MP" != "1" ] && continue _runvalgrind "$i" "$a -DMP_16BIT $CFLAGS" _runvalgrind "$i" "$a -DMP_32BIT $CFLAGS" else _runtest "$i" "$a $CFLAGS" [ "$WITH_LOW_MP" != "1" ] && continue _runtest "$i" "$a -DMP_16BIT $CFLAGS" _runtest "$i" "$a -DMP_32BIT $CFLAGS" fi done done _exit