#!/usr/bin/env bash # # # Bash script inclusion to test all GMT examples. # It sets the environment such that the examples are created as in the manual. test -z "$1" && exit 1 # Where the current script resides (need absolute path) script_name="$1" script_dir=$(dirname "${script_name}") local_script=$(basename "${script_name}") script="@GMT_SOURCE_DIR@/doc/examples/${script_name}" src="@GMT_SOURCE_DIR@/doc/examples/${script_dir}" # Is it a modern mode script? modern=$(grep "gmt begin" "$script" -c) # Is it a script that is known to fail? known2fail=$(grep "GMT_KNOWN_FAILURE" "$script" -c) # Any script override of GRAPHICSMAGICK_RMS? Must be a comment line of the format # GRAPHICSMAGICK_RMS = GRAPHICSMAGICK_RMS=$(grep "GRAPHICSMAGICK_RMS" "$script" | awk '{print $4}') if ! [ -x "${script}" ]; then echo "error: cannot execute script ${script}." >&2 exit 1 fi shift # Temporary change LANG to C LANG=C # Additional variables needed in gmtest GRAPHICSMAGICK="@GRAPHICSMAGICK@" # If no script-specific rms we use the system default if [ -z "$GRAPHICSMAGICK_RMS" ]; then GRAPHICSMAGICK_RMS="@GRAPHICSMAGICK_RMS@" fi # choose awk if command -v gawk >/dev/null 2>&1 ; then export AWK=gawk elif command -v nawk >/dev/null 2>&1 ; then export AWK=nawk else export AWK=awk fi # Reset error count ERROR=0 # valgrind gmt wrapper function gmt() { if [ -n "${VALGRIND_ARGS}" ]; then valgrind ${VALGRIND_ARGS} --log-file=valgrind_%p.log \ --dsymutil=yes @GMT_BINARY_DIR@/src/gmt "$@" else "@GMT_BINARY_DIR@/src/gmt" "$@" fi } # export function definitions to subshells export -f gmt # invalidate module calls without "gmt" prefix, which would bypass gmt from build dir . "@GMT_SOURCE_DIR@/test/invalidate_modules.sh" # Convert PS to PDF function make_pdf() { pdf="${ps%.ps}.pdf" test -f "$ps" || return 1 gmt psconvert -Tf -A -P "$ps" || ((++ERROR)) test -f "$pdf" || ((++ERROR)) } # Compare the ps file with its original. pscmp () { test -f "$ps" || return 1 if ! [ -x "$GRAPHICSMAGICK" ]; then echo "[PASS] (without comparison)" return fi for ps in *.ps ; do if [ ${known2fail} -eq 1 ]; then # No point running the comparison since we know it fails echo "${ps}: RMS Error = N/A [FAIL] (known failure)" now=$(date "+%F %T") echo "$now ${ps}: RMS Error = N/A Limit = $GRAPHICSMAGICK_RMS Failure = known" >> "@CMAKE_CURRENT_BINARY_DIR@/fail_count.txt" else # syntax: gm compare [ options ... ] reference-image [ options ... ] compare-image [ options ... ] rms=$("${GRAPHICSMAGICK}" compare -density 200 -maximum-error $GRAPHICSMAGICK_RMS -highlight-color magenta -highlight-style assign -metric rmse -file "${ps%.ps}.png" "$ps" "${src}/${ps}") || pscmpfailed="yes" rms=$(perl -ne 'print $1 if /Total: ([0-9.]+)/' <<< "$rms") if [ -z "$rms" ]; then rms="NA" else rms=$(printf "%.4f\n" $rms) fi if [ "$pscmpfailed" ]; then now=$(date "+%F %T") echo "${ps}: RMS Error = $rms [FAIL]" echo "$now ${ps}: RMS Error = N/A Limit = $GRAPHICSMAGICK_RMS Failure = new" >> "@CMAKE_CURRENT_BINARY_DIR@/fail_count.txt" make_pdf "$ps" # try to make pdf file ((++ERROR)) else test -z "$rms" && rms=N/A echo "${ps}: RMS Error = $rms [PASS]" fi fi done } # Make sure to cleanup at end function cleanup() { memtrack_err=0 for log_file in gmt_memtrack_*.log; do test -f ${log_file} || continue n_err=$(perl -lne '$a++ if /(Memory not freed|^!)/; END {print $a+0}' ${log_file}) (( memtrack_err += n_err )) || : # second assignment in case return code != 0 test ${n_err} -eq 0 && rm -f ${log_file} # remove logs w/o errors done echo "memtrack errors: $memtrack_err" >&2 valgrind_err=0 if [ -n "${VALGRIND_ARGS}" ]; then for log_file in valgrind_*.log; do test -f ${log_file} || continue n_err=$(perl -ne 'print $1 if /ERROR SUMMARY: ([0-9]+)/' ${log_file}) n_err=${n_err:-1} # if valgrind crashes itself, there is no ERROR SUMMARY (( valgrind_err += n_err )) || : # second assignment in case return code != 0 test ${n_err} -eq 0 && rm -f ${log_file} # remove logs w/o errors done echo "valgrind errors: $valgrind_err" >&2 fi cd "@CMAKE_CURRENT_BINARY_DIR@" # get out of exec_dir before removing it test "$ERROR" -eq 0 -a "$memtrack_err" -eq 0 -a "$valgrind_err" -eq 0 && rm -rf "$exec_dir" echo "exit status: $ERROR" >&2 exit $ERROR } # Test the output image before exiting function on_exit() { trap - EXIT # Restore EXIT trap pscmp cleanup } trap on_exit EXIT set -E # Shell functions and subshells need to inherit ERR trap function on_err() { trap - EXIT ERR SIGSEGV SIGTRAP SIGBUS # Restore trap ((++ERROR)) echo "ERROR: ${1}:${2}" >&2 # Report error line cleanup } trap 'on_err "${BASH_SOURCE}" "${LINENO}"' ERR SIGSEGV SIGTRAP SIGBUS # Create a temporary directory exec_dir in the build dir # Then copy all of its contents (except files excluded by GLOBIGNORE) # Run remainder of this GMT script there exec_dir="@CMAKE_CURRENT_BINARY_DIR@/${script_dir}" rm -rf "$exec_dir" mkdir -p "$exec_dir" cd "$exec_dir" shopt -s extglob GLOBIGNORE="!(*.bat|*.sh)" for file in "$src"/* ; do test -f "$file" && ln -s "$file" . done unset GLOBIGNORE # Run the original script via link from current directory ln -sf "$script" . # Make a script to capture everything that can be run again cat > gmtest.sh << EOF LANG=C # Define variables that are needed *within* test scripts export PATH="@GMT_BINARY_DIR@/src:\$PATH" unset GMT5_SHAREDIR export GMT_SHAREDIR="@GMT_SOURCE_DIR@/share" export GMT_DATADIR="$src" export GMT_SRCDIR="$src" export GSHHG_DIR="@GSHHG_PATH@" export DCW_DIR="@DCW_PATH@" export GMT_VERSION="@GMT_PACKAGE_VERSION_WITH_GIT_REVISION@" export GMT_BINARY_DIR="@GMT_BINARY_DIR@" export GMT_SOURCE_DIR="@GMT_SOURCE_DIR@" # Font lookup path for Ghostscript (invoked from gm compare and psconvert) export GS_FONTPATH="@CMAKE_CURRENT_SOURCE_DIR@/ex31/fonts" # Disable gmt end show from displaying plots export GMT_END_SHOW=off # Start with proper GMT defaults gmt set -Ds FORMAT_TIME_STAMP "Version 6" GMT_GRAPHICS_FORMAT ps # Modern mode needs a stable PPID but ctest messes that up when pipes are used if [ ${modern} -gt 0 ]; then export GMT_SESSION_NAME=\$\$ echo "Set GMT_SESSION_NAME = \$GMT_SESSION_NAME" script_mode=M fi # Now run the script . "${local_script}" EOF chmod 755 gmtest.sh . ./gmtest.sh # Modern mode needs to reestablish the $ps variable before exit if [ "X$script_mode" = "XM" ] && [ "X$ps" = "X" ]; then ps="${local_script%.sh}.ps" fi