diff options
Diffstat (limited to 'test/lib/utils.sh')
-rw-r--r-- | test/lib/utils.sh | 233 |
1 files changed, 164 insertions, 69 deletions
diff --git a/test/lib/utils.sh b/test/lib/utils.sh index 70d9f66..24b7f89 100644 --- a/test/lib/utils.sh +++ b/test/lib/utils.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +7,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e MAX_TRIES=4 @@ -15,7 +15,8 @@ IFS_NL=' ' die() { - echo "$@" >&2 + rm -f debug.log* + echo -e "$@" >&2 return 1 } @@ -34,16 +35,16 @@ rand_bytes() { cmds='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n' data=$( (eval "$cmds") 2>&1 | gzip ) - n_plus_50=$(expr $n + 50) + n_plus_50=$(( n + 50 )) # Ensure that $data has length at least 50+$n while :; do - len=$(echo "$data" | wc -c) - test $n_plus_50 -le $len && break; + len=${#data} # number of chars in $data + test "$n_plus_50" -le "$len" && break; data=$( (echo "$data"; eval "$cmds") 2>&1 | gzip ) done - echo "$data" | dd bs=1 skip=50 count=$n 2>/dev/null \ + echo "$data" | dd bs=1 skip=50 count="$n" 2>/dev/null \ | tr -c "$chars" "01234567$chars$chars$chars" } @@ -56,6 +57,8 @@ mkdtemp() { destdir=$1 template=$2 + test -d "$destdir" || die "DIR ('$destdir') does not exist." + case "$template" in *XXXX) ;; *) die "Invalid template: $template (must have a suffix of at least 4 X's)";; @@ -84,7 +87,7 @@ mkdtemp() { base_template=$(echo "$template" | sed 's/XX*$//') # Calculate how many X's we've just removed. - nx=$(expr length "$template" - length "$base_template") + nx=$(( ${#template} - ${#base_template} )) err= i=1 @@ -94,62 +97,136 @@ mkdtemp() { err=$(mkdir -m 0700 "$candidate_dir" 2>&1) && \ { echo "$candidate_dir"; return; } test $MAX_TRIES -le $i && break; - i=$(expr $i + 1) + i=$(( i + 1 )) done die "$err" } +# Like grep, just always print 1st. line +grep1_() { + awk -v pattern="${1}" 'NR==1 || $0~pattern' "${@:2}" +} + +stacktrace() { + trap - ERR + # i=1 - ignoring innermost frame - it is always stacktrace function + local i=1 n=${#BASH_LINENO[*]} + # n-=1 - ignoring last frame as well - it is not interesting + n=$(( n - 1 )) + + echo "## - $0:${BASH_LINENO[$((n-1))]}" + while [[ $i -lt $n ]]; do + echo "## $i ${FUNCNAME[$i]}() called from ${BASH_SOURCE[$((i+1))]}:${BASH_LINENO[$i]}" + i=$(( i + 1 )) + done +} + STACKTRACE() { trap - ERR - local i=0 + local i - echo "## - $0:${BASH_LINENO[0]}" - while FUNC=${FUNCNAME[$i]}; test "$FUNC" != "main"; do - echo "## $i ${FUNC}() called from ${BASH_SOURCE[$i]}:${BASH_LINENO[$i]}" - i=$(($i + 1)) - done + stacktrace - test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -n "$RUNNING_DMEVENTD" -o -f LOCAL_DMEVENTD || { - pgrep dmeventd &>/dev/null && \ - die "** During test dmeventd has been started!" - } + test "${LVM_TEST_PARALLEL:-0}" -eq 0 && test -z "$RUNNING_DMEVENTD" && \ + test ! -f LOCAL_DMEVENTD && pgrep dmeventd >DPID 2>/dev/null && { + echo "## ERROR: The test started dmeventd ($(< DPID)) unexpectedly." + kill "$(< DPID)" + } # Get backtraces from coredumps if which gdb &>/dev/null; then - echo bt full > gdb_commands.txt - echo l >> gdb_commands.txt - echo quit >> gdb_commands.txt - for core in $(ls core* 2>/dev/null); do - bin=$(gdb -batch -c "$core" 2>&1 | grep "generated by" | \ - sed -e "s,.*generated by \`\([^ ']*\).*,\1,") - gdb -batch -c "$core" -x gdb_commands.txt $(which "$bin") - done + # Check for all cores newer then TESTNAME file + # Assume users keep prefix 'core' + # TODO: possibly better integrate with coredumpctl & systemd + while IFS= read -r i; do + bin=$(gdb -batch -c "$i" 2>&1 | grep "generated by" | \ + sed -e "s,.*generated by \`\([^ ']*\).*,\1,") || continue + { + echo bt full + echo l + echo quit + } > gdb_commands.txt || rm -f gdb_commands.txt + + if test ! -s gdb_commands.txt ; then + echo "Out of disk space, can't check coredump $i generated by $bin." + continue + fi + + echo "## Checking coredump: $i generated by $bin." + gdb -batch -c "$i" -x gdb_commands.txt "$(which "$bin")" 2>/dev/null | \ + sed -e "s,^,## GDB: ," || continue + done < <(find . "$(dirname "$(sysctl -n kernel.core_pattern)")" \ + "/var/lib/systemd/coredump/" -name 'core*' -newer TESTNAME 2>/dev/null || true) fi - test -z "$LVM_TEST_NODEBUG" -a -f debug.log && { - sed -e "s,^,## DEBUG: ,;s,$top_srcdir/\?,," < debug.log - } - test -f SKIP_THIS_TEST && exit 200 + + test -z "$LVM_TEST_NODEBUG" && test -f TESTNAME && { + local name + local idx=0 + for i in debug.log* ; do + test -f "$i" || break # nothing is found (expands to debug.log*) + name=${i##debug.log_} + name=${name%%_*} + test "$name" = "DEBUG" && { name="$name$idx" ; idx=$(( idx + 1 )) ; } + echo "<======== Debug log $i ========>" + sed -e "s,^,## $name: ," "$i" + mv -f "$i" "debug_${i#debug.}" + done + if test -e strace.log ; then + echo "<======== Strace debug log ========>" + sed -e "s,^,## STRACE: ," strace.log + fi + if dmsetup info -c | grep -q "$PREFIX" ; then + echo "<======== Info ========>" + dmsetup info -c | grep1_ "$PREFIX"| sed -e "s,^,## DMINFO: ," + echo "<======== Active table ========>" + dmsetup table | grep "$PREFIX" | sed -e "s,^,## DMTABLE: ," + echo "<======== Inactive table ========>" + dmsetup table --inactive | grep "$PREFIX" | sed -e "s,^,## DMITABLE: ," + echo "<======== Status ========>" + dmsetup status --noflush | grep "$PREFIX" | sed -e "s,^,## DMSTATUS: ," + echo "<======== Tree ========>" + dmsetup ls --tree | sed -e "s,^,## DMTREE: ," + echo "<======== Recursive list of $DM_DEV_DIR ========>" + ls -lR -I bsg -I bus -I char -Idma_heap -I dri \ + -I hugepages -I input -I mqueue \ + -I net -I pts -I shm -I snd \ + -I tty?* -I usb -I vfio -I vcs?* \ + -I virtio-ports \ + "$DM_DEV_DIR" | sed -e "s,^,## LS_LR: ," + echo "<======== Udev DB content ========>" + for i in /sys/block/dm-* /sys/block/loop* ; do + udevadm info --query=all --path "$i" 2>/dev/null || true + done | sed -e "s,^,## UDEV: ," + fi + echo "<======== Free space ========>" + df -h | sed -e "s,^,## DF_H: ," + echo "<======== Script file \"$(< TESTNAME)\" ========>" + local script=$0 + test -f "$script" || script="$TESTOLDPWD/$0" + awk '{print "## Line:", NR, "\t", $0}' "$script" + } } init_udev_transaction() { - if test "$DM_UDEV_SYNCHRONISATION" = 1; then - local cookie=$(dmsetup udevcreatecookie) + if test "$DM_UDEV_SYNCHRONIZATION" = 1; then + local cookie + cookie=$(dmsetup udevcreatecookie) # Cookie is not generated if udev is not running! test -z "$cookie" || export DM_UDEV_COOKIE=$cookie fi } finish_udev_transaction() { - if test "$DM_UDEV_SYNCHRONISATION" = 1 -a -n "$DM_UDEV_COOKIE"; then - dmsetup udevreleasecookie + if test "$DM_UDEV_SYNCHRONIZATION" = 1 && test -n "${DM_UDEV_COOKIE-}" ; then + dmsetup udevreleasecookie || true unset DM_UDEV_COOKIE fi } teardown_udev_cookies() { - if test "$DM_UDEV_SYNCHRONISATION" = 1; then + if test "$DM_UDEV_SYNCHRONIZATION" = 1; then # Delete any cookies created more than 10 minutes ago # and not used in the last 10 minutes. # Log only non-zero semaphores count @@ -161,55 +238,73 @@ dm_info() { should dmsetup info --noheadings -c -o "$@" } +dm_status() { + should dmsetup status --noheadings "$@" +} + dm_table() { should dmsetup table "$@" } skip() { + set +vx # debug off + if test "$#" -eq 0; then + stacktrace + else + echo -e "TEST SKIPPED:" "$@" + fi touch SKIP_THIS_TEST exit 200 } -kernel_at_least() { - local major=$(uname -r | cut -d. -f1) - local minor=$(uname -r | cut -d. -f2 | cut -d- -f1) - - test "$major" -gt "$1" && return 0 - test "$major" -eq "$1" || return 1 - test "$minor" -gt "$2" && return 0 - test "$minor" -eq "$2" || return 1 - test -z "$3" && return 0 +get_real_devs() { + REAL_DEVICES=( $(<REAL_DEVICES) ) + export REAL_DEVICES +} - local minor2=$(uname -r | cut -d. -f3 | cut -d- -f1) - test -z "$minor2" -a "$3" -ne 0 && return 1 - test "$minor2" -ge "$3" 2>/dev/null || return 1 +get_devs() { + local IFS=$IFS_NL + DEVICES=( $(<DEVICES) ) + export DEVICES +# local DEVS=( $(<DEVICES) ) +# eval "$1"'=("${DEVS[@]}")' } prepare_test_vars() { vg="${PREFIX}vg" - lv=LV - - for i in $(seq 1 16); do - name="${PREFIX}pv$i" - dev="$DM_DEV_DIR/mapper/$name" - eval "dev$i=\"$dev\"" - eval "lv$i=LV$i" - eval "vg$i=${PREFIX}vg$i" + lv="LV" + + for i in {1..16}; do + eval "lv$i=\"LV$i\"" + eval "vg$i=\"${PREFIX}vg$i\"" done -} -# check if $abs_top_builddir was already set via 'lib/paths' -test -n "${abs_top_builddir+varset}" || . lib/paths || die "you must run make first" + if test -n "$LVM_TEST_DEVICE_LIST"; then + local count=0 + while read path; do + count=$(( count + 1 )) + eval "dev$count=\"$path\"" + done < "$LVM_TEST_DEVICE_LIST" + else + for i in {1..16}; do + eval "dev$i=\"$DM_DEV_DIR/mapper/${PREFIX}pv$i\"" + done + fi +} -case "$PATH" in -*"$abs_top_builddir/test/lib"*) ;; -*) - PATH="$abs_top_builddir/test/lib":$PATH - for d in daemons/dmeventd/plugins/mirror daemons/dmeventd/plugins/snapshot \ - daemons/dmeventd/plugins/lvm2 daemons/dmeventd liblvm tools libdm; do - LD_LIBRARY_PATH="$abs_top_builddir/$d":$LD_LIBRARY_PATH - done - export PATH LD_LIBRARY_PATH ;; -esac +if test -z "${abs_top_builddir+varset}" && test -z "${installed_testsuite+varset}"; then + . lib/paths || die "something went wrong -- lib/paths is missing?" +fi + +if test -z "${installed_testsuite+varset}"; then + case "$PATH" in + *"$abs_top_builddir/test/lib"*) ;; + *) + PATH="$abs_top_builddir/test/lib:$abs_top_builddir/test/api:$PATH" + LVM_BINARY=$(which lvm) + LD_LIBRARY_PATH="$abs_top_builddir/daemons/dmeventd:$abs_top_builddir/tools:$abs_top_builddir/libdm:$LD_LIBRARY_PATH" + export PATH LD_LIBRARY_PATH LVM_BINARY ;; + esac +fi test -z "$PREFIX" || prepare_test_vars |