#!/bin/sh # See LICENSE file for copyright and license details. if test $# = 0; then if "$0" fail for me; then printf 'Testing is broken!\n' >&2 exit 2 fi "$0" $$ r=$? rm -f -- .?-$$.tmp exit $r fi set -e test $# = 1 pid=$1 a=.a-$pid.tmp b=.b-$pid.tmp PATH="$(dirname -- "$0")/testutil:$PATH" export PATH stderr () { ("$@") 2>&1 >/dev/null } getlist () { getlist_list="$1" shift 1 if test $# = 0; then set cat; fi "$@" < libsyscalls.h \ | tr , '\n' \ | sed -n 's/^\s*LIBSYSCALLS_'"${getlist_list}"'_\([A-Z0-9_]\+\(\s*=\s*[ 0-9A-Fa-fxXULul()^&|!*/<>~+-]\+\)\?\)\b.*$/\1/p' \ | tr = ' ' \ | (i=0; while read name value; do if test -n "$value"; then i=$(( $(printf '%s\n' "$value" | tr -d 'ULul') )) i=$(printf '%s\n' "$i" | cut -d . -f 1) fi printf '%i %s\n' $(( i++ )) $name; done) } getnamelist () { getlist "$@" | cut -d ' ' -f 2 } getnumlist () { getlist "$@" | cut -d ' ' -f 1 } getname () { (getlist "$1" | grep "^$2 " | cut -d ' ' -f 2 | tee /dev/stderr | grep . >/dev/null) 2>&1 } getnum () { (getlist "$1" | grep " $2"\$ | cut -d ' ' -f 1 | tee /dev/stderr | grep . >/dev/null) 2>&1 } lookupname () { (printf '%s\n' "$1" | grep "^$2 " | cut -d ' ' -f 2 | tee /dev/stderr | grep . >/dev/null) 2>&1 } lookupnum () { (printf '%s\n' "$1" | grep " $2"\$ | cut -d ' ' -f 1 | tee /dev/stderr | grep . >/dev/null) 2>&1 } issupported () { if test $# = 1; then printf '%s\n' ${SUPPORTED_OSES} | grep -i "^$1"\$ > /dev/null else printf '%s\n' ${SUPPORTED_OSES} | grep -i "^$1"\$ > /dev/null && env | sed -n 's/^SUPPORTED_'"$1"'_ARCHES=//p' | xargs printf '%s\n' | grep -i "^$2"\$ > /dev/null fi } set -v # self check ( set -e stderr_printf () { printf "$@" >&2 } test "$(stderr_printf 'hello\n')" = '' test "$(stderr stderr_printf 'hello\n' 2>&1)" = 'hello' (! (false > $a) ) getname OS 0 (! getname OS) getnum OS LINUX (! getnum OS 0) getnamelist OS | grep LINUX getnamelist ARCH | grep AMD64_X32 getnumlist OS | grep '^0$' getnumlist ARCH | grep 10 getnumlist OS ${CPP} | grep '^0$' test -n "${CPP}" test "$(getname OS 0)" = LINUX test "$(getnum OS LINUX)" = 0 test "$(lookupnum "$(getlist OS)" LINUX)" = 0 test "$(lookupname "$(getlist OS)" 0)" = LINUX printf 'a\n' > $a printf 'b\n' > $b (! diff -u $a $b) printf 'a\n' > $b diff -u $a $b for os in ${SUPPORTED_OSES}; do issupported $os for arch in $(env | sed -n 's/^SUPPORTED_'"$os"'_ARCHES=//p' | xargs printf '%s\n'); do issupported $os $arch done done ) >/dev/null 2>/dev/null ### enums ### cpp_enum_clean () { $CPP < libsyscalls.h | grep -v '#' | tr '\n,{}' ' \n\n\n' } check_enum_good () { test -n "$(getnamelist "$@")" test -n "$(getnumlist "$@")" test -z "$(getnamelist "$@" | sort | uniq -d)" test -z "$(getnumlist "$@" | sort | uniq -d)" (( "$(getnumlist "$@" | sort -n | sed -n \$p)" <= 0xFFFF )) } check_enum_good OS check_enum_good ARCH check_enum_good CAT for cat in $(getnamelist CAT); do if test "$cat" = SUPPORT_PENDING || test "$cat" = NOT_IMPLEMENTED; then continue fi check_enum_good ${cat}_SUBCAT grep -i "enum.libsyscalls_${cat}_syscall_subcategory"'\s\+'"$cat"\\b < libsyscalls.h >/dev/null done check_enum_good SIGN check_enum_good ANNOTATION check_enum_good SECTION check_enum_good TYPE cpp_enum_clean types="$(getlist TYPE cpp_enum_clean)" ### libsyscalls errors ### strerror-all.tu > $a stderr perror-all.tu > $b diff -u $a $b test $(wc -l < $a) -ge 10 strerror-bad.tu > $a stderr perror-bad.tu > $b diff -u $a $b test $(wc -l < $a) = 2 grep -i '\(un\|not \)recogni[sz]ed' > /dev/null < $a test "$(sed 1q < $a)" = "$(sed 1d < $a)" for t in perror-bad.tu perror-all.tu; do stderr $t "" > $a stderr $t > $b diff -u $a $b stderr $t "test" > $a stderr $t > $b (! diff -u $a $b >/dev/null) stderr $t "test" > $a stderr $t | sed 's/^/test: /' > $b diff -u $a $b done strerror-all.tu > $a list-errors.tu > $b (! grep '^-' >/dev/null < $b) grep '^[0-9]\+ ' >/dev/null < $b grep '^[0-9]\+ LIBSYSCALLS_E_[A-Z]\+ ' >/dev/null < $b grep '^[0-9]\+ LIBSYSCALLS_E_[A-Z]\+ [A-Z].*[^.]$' >/dev/null < $b cut -d ' ' -f 3- < $b | diff -u $a - sed 1q < $b | grep '^0 LIBSYSCALLS_E_OK Success$' >/dev/null test -z "$(cut -d ' ' -f 1 < $b | sort | uniq -d)" test -z "$(cut -d ' ' -f 2 < $b | sort | uniq -d)" test -z "$(cut -d ' ' -f 3- < $b | sort | uniq -d)" test "$(get-error.tu LIBSYSCALLS_E_OK)" = 'Success' test "$(get-error.tu LIBSYSCALLS_E_OSNOSUP)" = 'Operating system not supported' test "$(get-error.tu LIBSYSCALLS_E_NOSUCHSYSCALL)" = 'No such system call' # This can be updated, its just to check that nothing is accidentally changed in LIBSYSCALLS_LIST_ERRORS cat > $a <<. 0 LIBSYSCALLS_E_OK Success 1 LIBSYSCALLS_E_OSNOSUP Operating system not supported 2 LIBSYSCALLS_E_ARCHNOSUP Architecture not supported for selected operating system 3 LIBSYSCALLS_E_NOSUCHSYSCALL No such system call 4 LIBSYSCALLS_E_NOERRORS There is no error listing for selected operating system 5 LIBSYSCALLS_E_NOSIGNALS There is no signal listing for selected operating system 6 LIBSYSCALLS_E_NOMEM Failed to allocate required memory 7 LIBSYSCALLS_E_INVAL Invalid arguments passed to function 8 LIBSYSCALLS_E_NOSUCHTYPE Type does not exist on the selected operating system or architecture 9 LIBSYSCALLS_E_ISSTRUCT Type is a structure or union . list-errors.tu | diff -u $a - ### System call number ranges ### for os in $(getnamelist OS); do osn=$(getnum OS $os) for arch in $(getnamelist ARCH); do archn=$(getnum ARCH $arch) get-syscall-range.tu $osn $archn $os $arch > $a min="$(sed -n 's/min: //p' < $a)" max="$(sed -n 's/max: //p' < $a)" test -n "$min" test -n "$max" if test $min = x || test $max = x; then (! issupported $os $arch) continue fi issupported $os $arch done done check_range () { if issupported $1 $2; then osn=$(getnum OS $1) archn=$(getnum ARCH $2) get-syscall-range.tu $osn $archn $1 $2 > $a min="$(sed -n 's/min: //p' < $a)" max="$(sed -n 's/max: //p' < $a)" test $min -le $3 test $max -ge $4 test -z "$5" || test $min -ge $5 fi } check_range LINUX AMD64 0 453 0 check_range LINUX AMD64_X32 0 547 0 check_range LINUX M68K 0 452 0 check_range LINUX PARISC_32 0 452 0 check_range LINUX PARISC_64 0 452 0 check_range LINUX SPARC_32 0 452 0 check_range LINUX I386 0 452 0 ### System call errors ### for os in $(getnamelist OS); do osn=$(getnum OS $os) for arch in $(getnamelist ARCH); do archn=$(getnum ARCH $arch) get-syscall-errors.tu $osn $archn $os $arch > $a grep -v '^[0-9]\+ -' >/dev/null < $a grep -v '^-' < $a > $b grep '^\([0-9]\+\) \1 ' < $a | diff -u $a - if issupported $os $arch; then (! test "$(cat $a)" = x) if test "$os" = LINUX; then signed=1 grep '^[0-9]\+ [0-9]\+ [A-Z0-9_]\+$' >/dev/null < $a test -z "$(grep -v '^[0-9]\+ [0-9]\+ [A-Z0-9_]\+$' < $a)" required="ERESTARTSYS ERESTARTNOINTR ERESTARTNOHAND ERESTART_RESTARTBLOCK EPERM ENOENT EDOM ELOOP" else continue; fi for req in $required; do grep '^-\?[0-9]\+ [0-9]\+ '"$req"\$ >/dev/null < $a done cut -d ' ' -f $(( 2 - signed )) < $a > $b && sort -n < $b | diff -u $b - if test -f testcases/errors-$os-$arch; then if ! diff -u testcases/errors-$os-$arch $a; then printf '\x1b[33m%s\x1b[m\n' "Maybe new errors have been added for $os on $arch" exit 1 fi fi else # Can still be successful because it may be hardcorded to # use the same table as another architecture that is supported, # however it cannot be successful if the OS is not supported issupported $os fi test -z "$(cut -d ' ' -f 1 < $a | sort | uniq -d)" test -z "$(cut -d ' ' -f 2 < $a | sort | uniq -d)" test -z "$(cut -d ' ' -f 3 < $a | sort | uniq -d)" done done test -f testcases/errors-LINUX-AMD64 test -f testcases/errors-LINUX-PARISC_32 test -f testcases/errors-LINUX-PARISC_64 (! diff -u testcases/errors-LINUX-AMD64 testcases/errors-LINUX-PARISC_32 >/dev/null) ### Operating system signals ### for os in $(getnamelist OS); do osn=$(getnum OS $os) for arch in $(getnamelist ARCH); do archn=$(getnum ARCH $arch) get-signals.tu $osn $archn $os $arch > $a grep -v '^[0-9]\+ -' >/dev/null < $a grep -v '^-' < $a > $b grep '^\([0-9]\+\) \1 ' < $a | diff -u $a - if issupported $os $arch; then (! test "$(cat $a)" = x) if test "$os" = LINUX; then signed=1 grep '^[0-9]\+ [0-9]\+ [A-Z0-9_+]\+$' >/dev/null < $a test -z "$(grep -v '^[0-9]\+ [0-9]\+ [A-Z0-9_+]\+$' < $a)" required="SIGKILL SIGTERM SIGCONT SIGSTOP SIGHUP _SIGRTMIN _SIGRTMIN+8" else continue; fi for req in $required; do grep '^-\?[0-9]\+ [0-9]\+ '"$req"\$ >/dev/null < $a done cut -d ' ' -f $(( 2 - signed )) < $a > $b && sort -n < $b | diff -u $b - if test -f testcases/signals-$os-$arch; then if ! diff -u testcases/signals-$os-$arch $a; then printf '\x1b[33m%s\x1b[m\n' "Maybe new signals have been added for $os on $arch" exit 1 fi fi else # Can still be successful because it may be hardcorded to # use the same table as another architecture that is supported, # however it cannot be successful if the OS is not supported issupported $os fi test -z "$(cut -d ' ' -f 1 < $a | sort | uniq -d)" test -z "$(cut -d ' ' -f 2 < $a | sort | uniq -d)" test -z "$(cut -d ' ' -f 3 < $a | sort | uniq -d)" done done test -f testcases/signals-LINUX-AMD64 ### Split register classifications ### test $(getnamelist SECTION | grep '_HALF$' | wc -l) -ge 8 for sec in $(getnamelist SECTION | grep '_HALF$'); do secn=$(getnum SECTION $sec) is-section-half.tu $secn (! is-section-quarter.tu $secn) test $(get-section-fraction.tu $secn) = 2 done test $(getnamelist SECTION | grep '_QUARTER$' | wc -l) -ge 4 for sec in $(getnamelist SECTION | grep '_QUARTER$'); do secn=$(getnum SECTION $sec) is-section-quarter.tu $secn (! is-section-half.tu $secn) test $(get-section-fraction.tu $secn) = 4 done secn="$(getnum SECTION WHOLE)" test -n "$secn" test $(get-section-fraction.tu $secn) = 1 ### Data types ### #in this test, we are assuming that char is 8 bits intsizes="8 16 32 64" cat > $b <<. 8Little 0 16Little 0 8 32Little 0 8 16 24 64Little 0 8 16 24 32 40 48 56 8Big 0 16Big 8 0 32Big 24 16 8 0 64Big 56 48 40 32 24 16 8 0 . byteorders="$(cat $b)" getbyteorder () { printf '%s\n' "$byteorders" | grep "^$1$2 " | cut -d ' ' -f 2- } sed '1,/LIST_ARCH_SPECS/d' < libsyscalls_get_datatype_description.c \ | sed '/#include/q' \ | sed 's/\(TO''DO\)\s*([^)]*)/\1/g' \ | sed -n 's/^\s*[A-Z_]\+(LIBSYSCALLS_ARCH_\([^)]*\)).*$/\1/p' \ | sed 's/,\s*/ /g' > $b grep '^AMD64 8 64 64 Little TWOS_COMPLEMENT' >/dev/null < $b grep '^AMD64_X32 8 32 32 Little TWOS_COMPLEMENT' >/dev/null < $b grep '^M68K 8 32 32 Big TWOS_COMPLEMENT' >/dev/null < $b grep '^PARISC_32 8 32 32 Big TWOS_COMPLEMENT' >/dev/null < $b grep '^PARISC_64 8 64 64 Big TWOS_COMPLEMENT' >/dev/null < $b grep '^SPARC_32 8 32 32 Big TWOS_COMPLEMENT' >/dev/null < $b grep '^I386 8 32 32 Little TWOS_COMPLEMENT' >/dev/null < $b archinfo="$(cat $b)" getbytesize () { printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 2 } getaddrsize () { printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 3 } getsizesize () { printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 4 } getendian () { printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 5 } getsign () { printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 6 } whole=$(getnum SECTION WHOLE) noannotation=$(getnum ANNOTATION NONE) for os in $(getnamelist OS); do osn=$(getnum OS $os) for arch in $(getnamelist ARCH); do archn=$(getnum ARCH $arch) if ! issupported $os $arch; then continue fi endian=$(getendian $arch) sign_representation=$(getsign $arch) if test ${sign_representation} = TWOS_COMPLEMENT; then min_is_minus_max=0 elif test ${sign_representation} = ONES_COMPLEMENT; then min_is_minus_max=1 elif test ${sign_representation} = SIGN_MAGNITUDE; then min_is_minus_max=1 elif test ${sign_representation} = EXCESS_HALF; then min_is_minus_max=0 else false fi sign_representation=$(getnum SIGN ${sign_representation}) for n in $intsizes; do type=INT$n desc="$(get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type)" printf '%s\n' "$desc" | grep "^width_in_bits = ${n}"\$ >/dev/null printf '%s\n' "$desc" | grep "^array_size = 1"\$ >/dev/null printf '%s\n' "$desc" | grep "^relative_position_of_array_size = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^absolute_position_of_array_size = -1"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_signed = 1"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_unsigned = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^min_is_minus_max = ${min_is_minus_max}"\$ >/dev/null printf '%s\n' "$desc" | grep "^sign_representation = ${sign_representation}"\$ >/dev/null printf '%s\n' "$desc" | grep "^annotation = ${noannotation}"\$ >/dev/null printf '%s\n' "$desc" | grep "^section = ${whole}"\$ >/dev/null printf '%s\n' "$desc" | grep "^byteorder = $(getbyteorder $n $endian)"\$ >/dev/null done for n in $intsizes; do type=UINT$n desc="$(get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type)" printf '%s\n' "$desc" | grep "^width_in_bits = ${n}"\$ >/dev/null printf '%s\n' "$desc" | grep "^array_size = 1"\$ >/dev/null printf '%s\n' "$desc" | grep "^relative_position_of_array_size = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^absolute_position_of_array_size = -1"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_signed = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_unsigned = 1"\$ >/dev/null printf '%s\n' "$desc" | grep "^annotation = ${noannotation}"\$ >/dev/null printf '%s\n' "$desc" | grep "^section = ${whole}"\$ >/dev/null printf '%s\n' "$desc" | grep "^byteorder = $(getbyteorder $n $endian)"\$ >/dev/null done type=VOID desc="$(get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type | tee $a)" printf '%s\n' "$desc" | grep "^width_in_bits = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^array_size = 1"\$ >/dev/null printf '%s\n' "$desc" | grep "^relative_position_of_array_size = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^absolute_position_of_array_size = -1"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_signed = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^is_unsigned = 0"\$ >/dev/null printf '%s\n' "$desc" | grep "^annotation = ${noannotation}"\$ >/dev/null printf '%s\n' "$desc" | grep "^section = ${whole}"\$ >/dev/null printf '%s\n' "$desc" | grep "^byteorder =\s*"\$ >/dev/null type=NO_RETURN get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type | diff -u $a - type=INT get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $a type=INT_SIGNAL get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b sed 's/^\(annotation\) .*$/\1 = '"$(getnum ANNOTATION SIGNAL)"'/' < $a | diff -u - $b type=INT_FD get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b sed 's/^\(annotation\) .*$/\1 = '"$(getnum ANNOTATION FD)"'/' < $a | diff -u - $b type=INT_ATFD get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b sed 's/^\(annotation\) .*$/\1 = '"$(getnum ANNOTATION ATFD)"'/' < $a | diff -u - $b type=LONG get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $a type=LONG_FD get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b sed 's/^\(annotation\) .*$/\1 = '"$(getnum ANNOTATION FD)"'/' < $a | diff -u - $b type=LONG_ATFD get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b sed 's/^\(annotation\) .*$/\1 = '"$(getnum ANNOTATION ATFD)"'/' < $a | diff -u - $b for type in SCHAR SHORT INT LONG LLONG PTRDIFF INTPTR SSIZE; do if test $type = SCHAR; then utype=UCHAR elif test $type = SSIZE; then utype=SIZE else utype=U$type fi get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $a grep "^width_in_bits = ." < $a >/dev/null grep "^array_size = 1"\$ < $a >/dev/null grep "^relative_position_of_array_size = 0"\$ < $a >/dev/null grep "^absolute_position_of_array_size = -1"\$ < $a >/dev/null grep "^is_signed = 1"\$ < $a >/dev/null grep "^is_unsigned = 0"\$ < $a >/dev/null grep "^min_is_minus_max = ${min_is_minus_max}"\$ < $a >/dev/null grep "^sign_representation = ${sign_representation}"\$ < $a >/dev/null grep "^annotation = ${noannotation}"\$ < $a >/dev/null grep "^section = ${whole}"\$ < $a >/dev/null n="$(grep "^width_in_bits = ." < $a | cut -d ' ' -f 3)" grep "^byteorder = $(getbyteorder $n $endian)"\$ < $a >/dev/null sed -e 's/^\(is_signed =\) .$/\1 0/' -e 's/^\(is_unsigned =\) .$/\1 1/' < $a > $b ( ! diff -u $b $a > /dev/null) grep -v '^\(min_is_minus_max\|sign_representation\) = ' < $b > $a ( ! diff -u $a $b > /dev/null) get-datatype-description.tu $osn $archn $(lookupnum "$types" $utype) $os $arch $utype > $b grep -v '^\(min_is_minus_max\|sign_representation\) = ' < $b | diff -u $a - if test $type = SCHAR; then xtypes=CHAR elif test $type = INTPTR; then xtypes="MEMORY_ADDRESS STRING STRINGS_THEN_NULL" else xtypes= fi for xtype in $xtypes; do get-datatype-description.tu $osn $archn $(lookupnum "$types" $xtype) $os $arch $xtype \ | grep -v '^\(min_is_minus_max\|sign_representation\) = ' > $b sed 's/^\(is_\(un\)signed =\) .$/\1 0/' < $a | diff -u - $b done done type=INTPTR get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $a type=PTRDIFF get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b diff -u $a $b type=DYNAMIC get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $a type=UNKNOWN get-datatype-description.tu $osn $archn $(lookupnum "$types" $type) $os $arch $type > $b diff -u $a $b done done printf '%s\n' "$types" | grep STRUCT >/dev/null printf '%s\n' "$types" | grep UNION >/dev/null structs="$(printf '%s\n' "$types" | grep '\(STRUCT\|UNION\)' | cut -d ' ' -f 1)" int=$(lookupnum "$types" INT) for os in $(getnamelist OS); do osn=$(getnum OS $os) for arch in $(getnamelist ARCH); do archn=$(getnum ARCH $arch) if ! issupported $os $arch; then continue fi ( ! is-datatype-struct.tu $osn $archn $int $os $arch INT ) for type in $structs; do is-datatype-struct.tu $osn $archn $type $os $arch 'some struct or union' done done done # TODO test libsyscalls_get_syscall # TODO test libsyscalls_get_syscall_display_info