1 #!/usr/bin/ksh
   2 #
   3 #
   4 # This file and its contents are supplied under the terms of the
   5 # Common Development and Distribution License ("CDDL"), version 1.0.
   6 # You may only use this file in accordance with the terms of version
   7 # 1.0 of the CDDL.
   8 #
   9 # A full copy of the text of the CDDL should have accompanied this
  10 # source.  A copy of the CDDL is also available via the Internet at
  11 # http://www.illumos.org/license/CDDL.
  12 #
  13 
  14 #
  15 # Copyright (c) 2019, Joyent, Inc.
  16 #
  17 
  18 #
  19 # Run all of the various CTF tests
  20 #
  21 
  22 unalias -a
  23 #set -o xtrace
  24 
  25 if [[ -z "$TMPDIR" ]]; then
  26         TMPDIR="/tmp"
  27 fi
  28 
  29 ctf_arg0=$(basename $0)
  30 ctf_root=$(cd $(dirname $0) && echo $PWD)
  31 ctf_tests=
  32 ctf_compiler="gcc"
  33 ctf_convert="ctfconvert"
  34 ctf_merge="ctfmerge"
  35 ctf_debugflags="-gdwarf-2 "
  36 ctf_mach32="-m32"
  37 ctf_mach64="-m64"
  38 ctf_32cflags="$ctf_mach32 $ctf_debugflags"
  39 ctf_64cflags="$ctf_mach64 $ctf_debugflags"
  40 ctf_temp="$TMPDIR/ctftest.$$.o"
  41 ctf_makefile="Makefile.ctftest"
  42 ctf_nerrs=0
  43 
  44 usage()
  45 {
  46         typeset msg="$*"
  47         [[ -z "$msg" ]] || echo "$msg" >&2
  48         cat <<USAGE >&2
  49 Usage: $ctf_arg0  [-c compiler] [-g flags] [-m ctfmerge] [-t ctfconvert]
  50 
  51         Runs the CTF test suite
  52 
  53         -c compiler             Use the specified compiler, defaults to 'gcc'
  54                                 on path.
  55         -g flags                Use flags to generate debug info. Defaults to
  56                                 "-gdwarf-2".
  57         -m ctfmerge             Use the specified ctfmerge, defaults to
  58                                 'ctfmerge' on path.
  59         -t ctfconvert           Use the specified ctfconvert, defaults to
  60                                 'ctfconvert' on path.
  61 USAGE
  62         exit 2
  63 }
  64 
  65 
  66 test_fail()
  67 {
  68         typeset msg="$*"
  69         [[ -z "$msg" ]] && msg="failed"
  70         echo "TEST FAILED: $msg" >&2
  71         ((ctf_nerrs++))
  72 }
  73 
  74 fatal()
  75 {
  76         typeset msg="$*"
  77         [[ -z "$msg" ]] && msg="failed"
  78         echo "$ctf_arg0: $msg" >&2
  79         rm -f "$ctf_tmp32" "$ctf_temp64"
  80         exit 1
  81 }
  82 
  83 check_env()
  84 {
  85         if which "$1" 2>/dev/null >/dev/null; then
  86                 return
  87         fi
  88 
  89         [[ -f "$1" ]] || fatal "failed to find tool $1"
  90 }
  91 
  92 announce()
  93 {
  94         cat << EOF
  95 Beginning CTF tests with the following settings:
  96 COMPILER:       $(which $ctf_compiler)
  97 CTFCONVERT:     $(which $ctf_convert)
  98 CTFMERGE:       $(which $ctf_merge)
  99 32-bit CFLAGS:  $ctf_32cflags
 100 64-bit CFLAGS:  $ctf_64cflags
 101 
 102 EOF
 103 }
 104 
 105 run_one()
 106 {
 107         typeset source=$1 checker=$2 flags=$3
 108 
 109         if ! "$ctf_compiler" $flags -o "$ctf_temp" -c "$source"; then
 110                 test_fail "failed to compile $source with flags: $flags"
 111                 return
 112         fi
 113 
 114         if ! "$ctf_convert" "$ctf_temp"; then
 115                 test_fail "failed to convert CTF in $source"
 116                 return
 117         fi
 118 
 119         if ! "$checker" "$ctf_temp"; then
 120                 test_fail "check for $source, $checker, failed"
 121                 return
 122         fi
 123 
 124         echo "TEST PASSED: $source $flags"
 125 }
 126 
 127 #
 128 # Perform a more complex build. The Makefile present will drive the
 129 # building of the artifacts and the running of the tests based on the
 130 # variables that we pass to it.
 131 #
 132 run_dir()
 133 {
 134         typeset dir outdir check32 check64 flags32 flags64
 135 
 136         dir=$1
 137         outdir="$TMPDIR/ctftest.$$-$(basename $d)"
 138         check32=$2
 139         flags32=$3
 140         check64=$4
 141         flags64=$5
 142 
 143         if ! mkdir $outdir; then
 144                 fatal "failed to make temporary directory '$outdir'"
 145         fi
 146 
 147         if ! make -C $dir -f Makefile.ctftest \
 148             BUILDDIR="$outdir" \
 149             CC="$ctf_compiler" \
 150             CFLAGS32="$ctf_mach32" \
 151             CFLAGS64="$ctf_mach64" \
 152             DEBUGFLAGS="$ctf_debugflags" \
 153             CTFCONVERT="$ctf_convert" \
 154             CTFMERGE="$ctf_merge" \
 155             build 1>/dev/null; then
 156                 rm -rf $outdir
 157                 test_fail "failed to build $dir"
 158                 return
 159         fi
 160 
 161         if ! make -C $dir -f Makefile.ctftest \
 162             BUILDDIR="$outdir" \
 163             CHECK32="$check32" \
 164             CHECK64="$check64" \
 165             run-test 1>/dev/null; then
 166                 rm -rf $outdir
 167                 test_fail "failed to run tests for $dir"
 168                 return
 169         fi
 170 
 171         rm -rf $outdir
 172         echo "TEST PASSED: $dir (dir)"
 173 }
 174 
 175 #
 176 # Find all of the tests that exist and then try to run them all. Tests
 177 # may either be a single file or a directory.
 178 #
 179 run_tests()
 180 {
 181         typeset t base check
 182         ctf_tests=$(ls "$ctf_root"/*.c)
 183         for t in $ctf_tests; do
 184                 base=$(basename "$t" .c)
 185                 check=$(echo "$base" | sed s/test-/check-/)
 186                 if [[ -f "$ctf_root/$check" ]]; then
 187                         run_one $t "$ctf_root/$check" "$ctf_32cflags"
 188                         run_one $t "$ctf_root/$check" "$ctf_64cflags"
 189                 elif [[ -f "$ctf_root/$check-32" && \
 190                     -f "$ctf_root/$check-64" ]]; then
 191                         run_one $t "$ctf_root/$check-32" "$ctf_32cflags"
 192                         run_one $t "$ctf_root/$check-64" "$ctf_64cflags"
 193                 else
 194                         test_fail "missing checker for $t"
 195                 fi
 196         done
 197 
 198         for d in $(find "$ctf_root" -maxdepth 1 -type d -name 'test-*'); do
 199                 [[ ! -f "$d/$ctf_makefile" ]] && continue
 200                 base=$(basename "$d")
 201                 check=$(echo "$base" | sed s/test-/check-/)
 202                 if [[ -f "$ctf_root/$check" ]]; then
 203                         run_dir $d "$ctf_root/$check" "$ctf_32cflags" \
 204                             "$ctf_root/$check" "$ctf_64cflags"
 205                 elif [[ -f "$ctf_root/$check-32" && \
 206                     -f "$ctf_root/$check-64" ]]; then
 207                         run_dir $d "$ctf_root/$check-32" "$ctf_32cflags" \
 208                             "$ctf_root/$check-64" "$ctf_64cflags"
 209                 else
 210                         test_fail "missing checker for $t"
 211                 fi
 212         done
 213 }
 214 
 215 while getopts ":c:g:m:t:" c $@; do
 216         case "$c" in
 217         c)
 218                 ctf_compiler=$OPTARG
 219                 ;;
 220         g)
 221                 ctf_debugflags=$OPTARG
 222                 ;;
 223         m)
 224                 ctf_merge=$OPTARG
 225                 ;;
 226         t)
 227                 ctf_convert=$OPTARG
 228                 ;;
 229         :)
 230                 usage "option requires an argument -- $OPTARG"
 231                 ;;
 232         *)
 233                 usage "invalid option -- $OPTARG"
 234                 ;;
 235         esac
 236 done
 237 
 238 ctf_32cflags="$ctf_mach32 $ctf_debugflags"
 239 ctf_64cflags="$ctf_mach64 $ctf_debugflags"
 240 
 241 check_env "$ctf_compiler"
 242 check_env "$ctf_convert"
 243 check_env "$ctf_merge"
 244 announce
 245 
 246 run_tests
 247 
 248 if [[ $ctf_nerrs -ne 0 ]]; then
 249         if [[ $ctf_nerrs -eq 1 ]]; then
 250                 printf "\n%s: %u test failed\n" "$ctf_arg0" "$ctf_nerrs"
 251         else
 252                 printf "\n%s: %u tests failed\n" "$ctf_arg0" "$ctf_nerrs"
 253         fi
 254 else
 255         printf "\n%s: All tests passed successfully\n" "$ctf_arg0"
 256         exit 0
 257 fi