libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

zzuf_test_runner.sh (6070B)


      1 #!/bin/sh
      2 #
      3 # Run one fuzzing test with zzuf intercepting the network input of the
      4 # test process itself.
      5 #
      6 # Recognised environment variables:
      7 #   ZZUF             the zzuf command (set by configure)
      8 #   ZZUF_SEED        the single seed to use (default "0")
      9 #   ZZUF_SEED_START  the first seed of a seed range (overrides ZZUF_SEED)
     10 #   ZZUF_SEED_STOP   the last seed of a seed range
     11 #   ZZUF_FLAGS       additional flags for zzuf
     12 #   SOCAT            the socat command (set by configure)
     13 #   SOCAT_FLAGS      additional flags for socat
     14 #
     15 # This script is POSIX shell only, do not use any bashism.
     16 
     17 mhd_listen_ip='127.0.0.1'
     18 max_runtime_sec='1800'
     19 
     20 if test "x${ZZUF}" = "xno" ; then
     21   echo "zzuf command missing" 1>&2
     22   exit 77
     23 fi
     24 
     25 if command -v "${ZZUF}" > /dev/null 2>&1 ; then : ; else
     26   echo "zzuf command missing" 1>&2
     27   exit 77
     28 fi
     29 
     30 # Build the "--seed" parameter for zzuf.
     31 # A seed range makes zzuf start one child per seed, which is what CI uses
     32 # to sweep a large number of seeds.
     33 zzuf_seed_param=''
     34 if test -n "${ZZUF_SEED_START}" ; then
     35   if test -n "${ZZUF_SEED_STOP}" ; then
     36     zzuf_seed_param="--seed=${ZZUF_SEED_START}:${ZZUF_SEED_STOP}"
     37     seed_descr="range ${ZZUF_SEED_START}:${ZZUF_SEED_STOP}"
     38   else
     39     zzuf_seed_param="--seed=${ZZUF_SEED_START}"
     40     seed_descr="${ZZUF_SEED_START}"
     41   fi
     42 elif test -n "${ZZUF_SEED}" ; then
     43   zzuf_seed_param="--seed=${ZZUF_SEED}"
     44   seed_descr="${ZZUF_SEED}"
     45 else
     46   seed_descr="(zzuf default)"
     47 fi
     48 
     49 test_log=''
     50 
     51 cleanup_log ()
     52 {
     53   if test -n "${test_log}" ; then
     54     rm -f "${test_log}"
     55     test_log=''
     56   fi
     57 }
     58 
     59 # Print a loud, easy to grep report about a failing run, including the
     60 # seed(s) that produced the failure.
     61 # $1: the exit code of zzuf
     62 report_failure ()
     63 {
     64   failed_seeds=''
     65   if test -n "${test_log}" && test -r "${test_log}" ; then
     66     # zzuf prints one line per child, e.g.
     67     #   zzuf[s=17,r=0.012345]: signal 6 (SIGABRT)
     68     failed_seeds=`grep -E '^zzuf\[s=[0-9]+' "${test_log}" 2> /dev/null | \
     69       grep -E 'signal|exit|crash|abort|too (slow|much|many)' 2> /dev/null | \
     70       sed -e 's/^zzuf\[s=//' -e 's/[^0-9].*$//' | \
     71       sort -n -u | tr '\n' ' '`
     72   fi
     73   echo '' 1>&2
     74   echo '###############################################################' 1>&2
     75   echo '## FUZZING TEST FAILED' 1>&2
     76   echo "## test        : ${test_descr}" 1>&2
     77   echo "## exit code   : $1" 1>&2
     78   echo "## seed(s) used: ${seed_descr}" 1>&2
     79   if test -n "${failed_seeds}" ; then
     80     echo "## FAILING SEED(S): ${failed_seeds}" 1>&2
     81     echo '## Replay a single failing seed with:' 1>&2
     82     for one_seed in ${failed_seeds} ; do
     83       echo "##   make ZZUF_SEED=${one_seed} TESTS=${test_name} check" 1>&2
     84     done
     85   else
     86     echo '## No failing seed could be extracted from the zzuf output.' 1>&2
     87     echo '## Replay the whole run with:' 1>&2
     88     if test -n "${ZZUF_SEED_START}" ; then
     89       echo "##   make ZZUF_SEED_START=${ZZUF_SEED_START} \
     90 ZZUF_SEED_STOP=${ZZUF_SEED_STOP} TESTS=${test_name} check" 1>&2
     91     else
     92       echo "##   make ZZUF_SEED=${ZZUF_SEED} TESTS=${test_name} check" 1>&2
     93     fi
     94   fi
     95   echo '###############################################################' 1>&2
     96   echo '' 1>&2
     97 }
     98 
     99 run_with_socat ()
    100 {
    101   echo "Trying to run the test with socat..."
    102   script_dir=""
    103   if command -v dirname > /dev/null 2>&1 ; then
    104     test_dir=`dirname /`
    105     if test "x${test_dir}" = "x/" ; then
    106       if dirname "$1" > /dev/null 2>&1 ; then
    107         script_dir=`dirname "$1"`
    108         if test -n "${script_dir}" ; then
    109           # Assume script is not in the root dir
    110           script_dir="${script_dir}/"
    111         else
    112           script_dir="./"
    113         fi
    114       fi
    115     fi
    116   fi
    117   if test -z "${script_dir}" ; then
    118     if echo "$1" | sed 's|[^/]*$||' > /dev/null 2>&1 ; then
    119       script_dir=`echo "$1" | sed 's|[^/]*$||'`
    120         if test -z "${script_dir}" ; then
    121           script_dir="./"
    122         fi
    123     fi
    124   fi
    125   if test -z "${script_dir}" ; then
    126     echo "Cannot determine script location, will try current directory." 1>&2
    127     script_dir="./"
    128   fi
    129   cleanup_log
    130   $SHELL "${script_dir}zzuf_socat_test_runner.sh" "$@"
    131   exit $?
    132 }
    133 
    134 test_descr="$*"
    135 test_name=`echo "$1" | sed 's|^.*/||'`
    136 trap 'cleanup_log' EXIT
    137 
    138 # zzuf cannot pass-through the return value of checked program
    139 # so try the direct dry-run first to get possible 77 or 99 codes
    140 echo "## Dry-run of the $* ..."
    141 if "$@" --dry-run ; then
    142   echo "# Dry-run succeeded."
    143 else
    144   res_code=$?
    145   echo "Dry-run failed with exit code $res_code." 1>&2
    146   if test $res_code -ne 99; then
    147     run_with_socat "$@"
    148   fi
    149   echo "$* will not be run with zzuf." 1>&2
    150   exit $res_code
    151 fi
    152 
    153 # fuzz the input only for IP ${mhd_listen_ip}. libcurl and the raw client
    154 # use another IP in these tests, therefore the input of the clients is not
    155 # fuzzed.
    156 zzuf_all_params="--ratio=0.001:0.4 --autoinc --verbose --signal \
    157  --max-usertime=${max_runtime_sec} --check-exit --network \
    158  --allow=${mhd_listen_ip} --exclude=."
    159 
    160 if test -n "${zzuf_seed_param}" ; then
    161   zzuf_all_params="${zzuf_all_params} ${zzuf_seed_param}"
    162 fi
    163 
    164 if test -n "${ZZUF_FLAGS}" ; then
    165   zzuf_all_params="${zzuf_all_params} ${ZZUF_FLAGS}"
    166 fi
    167 
    168 # Uncomment the next line to see more data in logs
    169 #zzuf_all_params="${zzuf_all_params} -dd"
    170 
    171 echo "## Dry-run of the $* with zzuf..."
    172 if "$ZZUF" ${zzuf_all_params} "$@" --dry-run ; then
    173   echo "# Dry-run with zzuf succeeded."
    174 else
    175   res_code=$?
    176   echo "$* cannot be run with zzuf directly." 1>&2
    177   run_with_socat "$@"
    178   exit $res_code
    179 fi
    180 
    181 echo "## Real test of $* with zzuf (seed: ${seed_descr})..."
    182 if command -v tee > /dev/null 2>&1 ; then
    183   test_log="${TMPDIR:-/tmp}/mhd_zzuf_$$.log"
    184   rc_file="${test_log}.rc"
    185   { "$ZZUF" ${zzuf_all_params} "$@" ; echo $? > "${rc_file}" ; } 2>&1 | \
    186     tee "${test_log}"
    187   if test -r "${rc_file}" ; then
    188     res_code=`cat "${rc_file}"`
    189   else
    190     res_code=1
    191   fi
    192   rm -f "${rc_file}"
    193 else
    194   # No 'tee': run without capturing, the failing seed has to be taken
    195   # from the test log by hand.
    196   "$ZZUF" ${zzuf_all_params} "$@"
    197   res_code=$?
    198 fi
    199 
    200 if test "x${res_code}" != "x0" ; then
    201   report_failure "${res_code}"
    202 fi
    203 cleanup_log
    204 exit ${res_code}