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}