Home | History | Annotate | Download | only in tests-m32
      1 #!/bin/sh
      2 #
      3 # Copyright (c) 2011-2016 Dmitry V. Levin <ldv (at] altlinux.org>
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions
      8 # are met:
      9 # 1. Redistributions of source code must retain the above copyright
     10 #    notice, this list of conditions and the following disclaimer.
     11 # 2. Redistributions in binary form must reproduce the above copyright
     12 #    notice, this list of conditions and the following disclaimer in the
     13 #    documentation and/or other materials provided with the distribution.
     14 # 3. The name of the author may not be used to endorse or promote products
     15 #    derived from this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 ME_="${0##*/}"
     29 LOG="$ME_.tmp"
     30 OUT="$LOG.out"
     31 EXP="$LOG.exp"
     32 NAME="${ME_%.test}"
     33 
     34 warn_() { printf >&2 '%s\n' "$*"; }
     35 fail_() { warn_ "$ME_: failed test: $*"; exit 1; }
     36 skip_() { warn_ "$ME_: skipped test: $*"; exit 77; }
     37 framework_failure_() { warn_ "$ME_: framework failure: $*"; exit 99; }
     38 framework_skip_() { warn_ "$ME_: framework skip: $*"; exit 77; }
     39 
     40 check_prog()
     41 {
     42 	type "$@" > /dev/null 2>&1 ||
     43 		framework_skip_ "$* is not available"
     44 }
     45 
     46 dump_log_and_fail_with()
     47 {
     48 	cat < "$LOG"
     49 	fail_ "$*"
     50 }
     51 
     52 run_prog()
     53 {
     54 	if [ $# -eq 0 ]; then
     55 		set -- "./$NAME"
     56 	fi
     57 	args="$*"
     58 	"$@" || {
     59 		rc=$?
     60 		if [ $rc -eq 77 ]; then
     61 			skip_ "$args exited with code 77"
     62 		else
     63 			fail_ "$args failed with code $rc"
     64 		fi
     65 	}
     66 }
     67 
     68 
     69 run_prog_skip_if_failed()
     70 {
     71 	args="$*"
     72 	"$@" || framework_skip_ "$args failed with code $?"
     73 }
     74 
     75 run_strace()
     76 {
     77 	> "$LOG" || fail_ "failed to write $LOG"
     78 	args="$*"
     79 	$STRACE -o "$LOG" "$@" ||
     80 		dump_log_and_fail_with "$STRACE $args failed with code $?"
     81 }
     82 
     83 run_strace_merge()
     84 {
     85 	rm -f -- "$LOG".[0-9]*
     86 	run_strace -ff -tt "$@"
     87 	"$srcdir"/../strace-log-merge "$LOG" > "$LOG" ||
     88 		dump_log_and_fail_with 'strace-log-merge failed with code $?'
     89 	rm -f -- "$LOG".[0-9]*
     90 }
     91 
     92 check_gawk()
     93 {
     94 	check_prog gawk
     95 	check_prog grep
     96 
     97 	local program="$1"; shift
     98 	if grep '^@include[[:space:]]' < "$program" > /dev/null; then
     99 		gawk '@include "/dev/null"' < /dev/null ||
    100 			framework_skip_ 'gawk does not support @include'
    101 	fi
    102 }
    103 
    104 # Usage: [FILE_TO_CHECK [AWK_PROGRAM [ERROR_MESSAGE [EXTRA_AWK_OPTIONS...]]]]
    105 # Check whether AWK_PROGRAM matches FILE_TO_CHECK using gawk.
    106 # If it doesn't, dump FILE_TO_CHECK and fail with ERROR_MESSAGE.
    107 match_awk()
    108 {
    109 	local output program error
    110 	if [ $# -eq 0 ]; then
    111 		output="$LOG"
    112 	else
    113 		output="$1"; shift
    114 	fi
    115 	if [ $# -eq 0 ]; then
    116 		program="$srcdir/$NAME.awk"
    117 	else
    118 		program="$1"; shift
    119 	fi
    120 	if [ $# -eq 0 ]; then
    121 		error="$STRACE $args output mismatch"
    122 	else
    123 		error="$1"; shift
    124 	fi
    125 
    126 	check_gawk "$program"
    127 
    128 	AWKPATH="$srcdir" gawk -f "$program" "$@" < "$output" || {
    129 		cat < "$output"
    130 		fail_ "$error"
    131 	}
    132 }
    133 
    134 # Usage: [FILE_TO_CHECK [FILE_TO_COMPATE_WITH [ERROR_MESSAGE]]]
    135 # Check whether FILE_TO_CHECK differs from FILE_TO_COMPATE_WITH.
    136 # If it does, dump the difference and fail with ERROR_MESSAGE.
    137 match_diff()
    138 {
    139 	local output expected error
    140 	if [ $# -eq 0 ]; then
    141 		output="$LOG"
    142 	else
    143 		output="$1"; shift
    144 	fi
    145 	if [ $# -eq 0 ]; then
    146 		expected="$srcdir/$NAME.expected"
    147 	else
    148 		expected="$1"; shift
    149 	fi
    150 	if [ $# -eq 0 ]; then
    151 		error="$STRACE $args output mismatch"
    152 	else
    153 		error="$1"; shift
    154 	fi
    155 
    156 	check_prog diff
    157 
    158 	diff -- "$expected" "$output" ||
    159 		fail_ "$error"
    160 }
    161 
    162 # Usage: [FILE_TO_CHECK [FILE_WITH_PATTERNS [ERROR_MESSAGE]]]
    163 # Check whether all patterns listed in FILE_WITH_PATTERNS
    164 # match FILE_TO_CHECK using egrep.
    165 # If at least one of these patterns does not match,
    166 # dump both files and fail with ERROR_MESSAGE.
    167 match_grep()
    168 {
    169 	local output patterns error pattern cnt failed=
    170 	if [ $# -eq 0 ]; then
    171 		output="$LOG"
    172 	else
    173 		output="$1"; shift
    174 	fi
    175 	if [ $# -eq 0 ]; then
    176 		patterns="$srcdir/$NAME.expected"
    177 	else
    178 		patterns="$1"; shift
    179 	fi
    180 	if [ $# -eq 0 ]; then
    181 		error="$STRACE $args output mismatch"
    182 	else
    183 		error="$1"; shift
    184 	fi
    185 
    186 	check_prog wc
    187 	check_prog grep
    188 
    189 	cnt=1
    190 	while read -r pattern; do
    191 		LC_ALL=C grep -E -x -e "$pattern" < "$output" > /dev/null || {
    192 			test -n "$failed" || {
    193 				echo 'Failed patterns of expected output:'
    194 				failed=1
    195 			}
    196 			printf '#%d: %s\n' "$cnt" "$pattern"
    197 		}
    198 		cnt=$(($cnt + 1))
    199 	done < "$patterns"
    200 	test -z "$failed" || {
    201 		echo 'Actual output:'
    202 		cat < "$output"
    203 		fail_ "$error"
    204 	}
    205 }
    206 
    207 # Usage: run_strace_match_diff [args to run_strace]
    208 run_strace_match_diff()
    209 {
    210 	args="$*"
    211 	[ -n "$args" -a -z "${args##*-e trace=*}" ] ||
    212 		set -- -e trace="$NAME" "$@"
    213 	run_prog > /dev/null
    214 	run_strace "$@" $args > "$EXP"
    215 	match_diff "$LOG" "$EXP"
    216 	rm -f "$EXP"
    217 }
    218 
    219 # Print kernel version code.
    220 # usage: kernel_version_code $(uname -r)
    221 kernel_version_code()
    222 {
    223 	(
    224 		set -f
    225 		IFS=.
    226 		set -- $1
    227 		v1="${1%%[!0-9]*}" && [ -n "$v1" ] || v1=0
    228 		v2="${2%%[!0-9]*}" && [ -n "$v2" ] || v2=0
    229 		v3="${3%%[!0-9]*}" && [ -n "$v3" ] || v3=0
    230 		echo "$(($v1 * 65536 + $v2 * 256 + $v3))"
    231 	)
    232 }
    233 
    234 # Usage: require_min_kernel_version_or_skip 3.0
    235 require_min_kernel_version_or_skip()
    236 {
    237 	local uname_r
    238 	uname_r="$(uname -r)"
    239 
    240 	[ "$(kernel_version_code "$uname_r")" -ge \
    241 	  "$(kernel_version_code "$1")" ] ||
    242 		skip_ "the kernel release $uname_r is not $1 or newer"
    243 }
    244 
    245 # Usage: grep_pid_status $pid GREP-OPTIONS...
    246 grep_pid_status()
    247 {
    248 	local pid
    249 	pid=$1; shift
    250 	cat < "/proc/$pid/status" | grep "$@"
    251 }
    252 
    253 check_prog cat
    254 check_prog rm
    255 
    256 rm -f "$LOG"
    257 
    258 [ -n "${STRACE-}" ] || {
    259 	STRACE=../strace
    260 	case "${LOG_COMPILER-} ${LOG_FLAGS-}" in
    261 		*--suppressions=*--error-exitcode=*--tool=*)
    262 			# add valgrind command prefix
    263 			STRACE="${LOG_COMPILER-} ${LOG_FLAGS-} $STRACE"
    264 			;;
    265 	esac
    266 }
    267 
    268 : "${TIMEOUT_DURATION:=60}"
    269 : "${SLEEP_A_BIT:=sleep 1}"
    270 
    271 [ -z "${VERBOSE-}" ] ||
    272 	set -x
    273