1# common.sh - an include file for commonly used functions for test code. 2# BSD licensed (see LICENSE file). 3# 4# Version 7 5# 2025-04-04: speed up kill_pid. 6# 2023-12-06: list wait_for_soa_serial in overview 7# 2023-12-06: get_ldns_notify, skip_test and teststep, and previous changes 8# also included are wait_logfile, cpu_count, process_cpu_list, and 9# kill_from_pidfile, and use HOME variable for HOME/bin. 10# 2011-04-06: tpk wait_logfile to wait (with timeout) for a logfile line to appear 11# 2011-02-23: get_pcat for PCAT, PCAT_DIFF and PCAT_PRINT defines. 12# 2011-02-18: ports check on BSD,Solaris. wait_nsd_up. 13# 2011-02-11: first version. 14# 15# include this file from a tdir script with 16# . ../common.sh 17# 18# overview of functions available: 19# error x : print error and exit 20# info x : print info 21# test_tool_avail x : see if program in path and complain, exit if not. 22# get_ldns_testns : set LDNS_TESTNS to executable ldns-testns 23# get_ldns_notify : set LDNS_NOTIFY to executable ldns-notify 24# get_make : set MAKE to gmake or make tool. 25# get_gcc : set cc or gcc in CC 26# get_pcat : set PCAT, PCAT_DIFF and PCAT_PRINT executables. 27# set_doxygen_path : set doxygen path 28# skip_if_in_list : set SKIP=1 if name in list and tool not available. 29# get_random_port x : get RND_PORT a sequence of free random port numbers. 30# wait_logfile : wait on logfile to see entry. 31# wait_server_up : wait on logfile to see when server comes up. 32# wait_ldns_testns_up : wait for ldns-testns to come up. 33# wait_unbound_up : wait for unbound to come up. 34# wait_petal_up : wait for petal to come up. 35# wait_nsd_up : wait for nsd to come up. 36# wait_server_up_or_fail: wait for server to come up or print a failure string 37# wait_for_soa_serial : wait and dig at server for serial. 38# skip_test x : print message and skip test (must be called in .pre) 39# kill_pid : kill a server, make sure and wait for it to go down. 40# cpu_count : get number of cpus in system 41# process_cpu_list : get cpu affinity list for process 42# kill_from_pidfile : kill the pid in the given pid file 43# teststep : print the current test step in the output 44 45 46# print error and exit 47# $0: name of program 48# $1: error to printout. 49error () { 50 echo "$0: error: $1" >&2 51 exit 1 52} 53 54# print info 55# $0: name of program 56# $1: to printout. 57info () { 58 echo "$0: info: $1" 59} 60 61# test if 'tool' is available in path and complain otherwise. 62# $1: tool 63test_tool_avail () { 64 if test ! -x "`which $1 2>&1`"; then 65 echo No "$1" in path 66 exit 1 67 fi 68} 69 70# get ldns-testns tool in LDNS_TESTNS variable. 71get_ldns_testns () { 72 if test -x "`which ldns-testns 2>&1`"; then 73 LDNS_TESTNS=ldns-testns 74 else 75 LDNS_TESTNS=$HOME/bin/ldns-testns 76 fi 77} 78 79# get ldns-notify tool in LDNS_NOTIFY variable. 80get_ldns_notify () { 81 if test -x "`which ldns-notify 2>&1`"; then 82 LDNS_NOTIFY=ldns-notify 83 else 84 LDNS_NOTIFY=$HOME/bin/ldns-notify 85 fi 86} 87 88# get make tool in MAKE variable, gmake is used if present. 89get_make () { 90 if test -x "`which gmake 2>&1`"; then 91 MAKE=gmake 92 else 93 MAKE=make 94 fi 95} 96 97# get cc tool in CC variable, gcc is used if present. 98get_gcc () { 99 if test -x "`which gcc 2>&1`"; then 100 CC=gcc 101 else 102 CC=cc 103 fi 104} 105 106# get pcat, pcat-print and pcat-diff 107get_pcat () { 108 PCAT=`which pcat` 109 PCAT_PRINT=`which pcat-print` 110 PCAT_DIFF=`which pcat-diff` 111} 112 113# set SKIP=1 if the name is in list and tool is not available. 114# $1: name of package to check. 115# $2: list of packages that need the tool. 116# #3: name of the tool required. 117skip_if_in_list () { 118 if echo $2 | grep $1 >/dev/null; then 119 if test ! -x "`which $3 2>&1`"; then 120 SKIP=1; 121 fi 122 fi 123} 124 125# Print a message and skip the test. Must be called in the .pre file. 126# $1: message to print. 127skip_test () { 128 echo "$1" 129 exit 3 130} 131 132# function to get a number of random port numbers. 133# $1: number of random ports. 134# RND_PORT is returned as the starting port number 135get_random_port () { 136 local plist 137 local cont 138 local collisions 139 local i 140 local MAXCOLLISION=1000 141 cont=1 142 collisions=0 143 while test "$cont" = 1; do 144 #netstat -n -A ip -A ip6 -a | sed -e "s/^.*:\([0-9]*\) .*$/\1/" 145 RND_PORT=$(( $RANDOM + 5354 )) 146 # depending on uname try to check for collisions in port numbers 147 case "`uname`" in 148 linux|Linux) 149 plist=`netstat -n -A ip -A ip6 -a 2>/dev/null | sed -e 's/^.*:\([0-9]*\) .*$/\1/'` 150 ;; 151 FreeBSD|freebsd|NetBSD|netbsd|OpenBSD|openbsd) 152 plist=`netstat -n -a | grep "^[ut][dc]p[46] " | sed -e 's/^.*\.\([0-9]*\) .*$/\1/'` 153 ;; 154 Solaris|SunOS) 155 plist=`netstat -n -a | sed -e 's/^.*\.\([0-9]*\) .*$/\1/' | grep '^[0-9]*$'` 156 ;; 157 *) 158 plist="" 159 ;; 160 esac 161 cont=0 162 for (( i=0 ; i < $1 ; i++ )); do 163 if echo "$plist" | grep '^'`expr $i + $RND_PORT`'$' >/dev/null 2>&1; then 164 cont=1; 165 collisions=`expr $collisions + 1` 166 fi 167 done 168 if test $collisions = $MAXCOLLISION; then 169 error "too many collisions getting random port number" 170 fi 171 done 172} 173 174# wait for a logfile line to appear, with a timeout. 175# pass <logfilename> <string to watch> <timeout> 176# $1 : logfilename 177# $2 : string to watch for. 178# $3 : timeout in seconds. 179# exits with failure if it times out 180wait_logfile () { 181 local WAIT_THRES=30 182 local MAX_UP_TRY=`expr $3 + $WAIT_THRES` 183 local try 184 for (( try=0 ; try <= $MAX_UP_TRY ; try++ )) ; do 185 if test -f $1 && grep -F "$2" $1 >/dev/null; then 186 #echo "done on try $try" 187 break; 188 fi 189 if test $try -eq $MAX_UP_TRY; then 190 echo "Logfile in $1 did not get $2!" 191 cat $1 192 exit 1; 193 fi 194 if test $try -ge $WAIT_THRES; then 195 sleep 1 196 fi 197 done 198} 199 200# wait for server to go up, pass <logfilename> <string to watch> 201# $1 : logfilename 202# $2 : string to watch for. 203# exits with failure if it does not come up 204wait_server_up () { 205 local WAIT_THRES=30 206 local MAX_UP_TRY=120 207 local try 208 for (( try=0 ; try <= $MAX_UP_TRY ; try++ )) ; do 209 if test -f $1 && grep -F "$2" $1 >/dev/null; then 210 #echo "done on try $try" 211 break; 212 fi 213 if test $try -eq $MAX_UP_TRY; then 214 echo "Server in $1 did not go up!" 215 cat $1 216 exit 1; 217 fi 218 if test $try -ge $WAIT_THRES; then 219 sleep 1 220 fi 221 done 222} 223 224# wait for ldns-testns to come up 225# $1 : logfilename that is watched. 226wait_ldns_testns_up () { 227 wait_server_up "$1" "Listening on port" 228} 229 230# wait for unbound to come up 231# string 'Start of service' in log. 232# $1 : logfilename that is watched. 233wait_unbound_up () { 234 wait_server_up "$1" "start of service" 235} 236 237# wait for petal to come up 238# string 'petal start' in log. 239# $1 : logfilename that is watched. 240wait_petal_up () { 241 wait_server_up "$1" "petal start" 242} 243 244# wait for nsd to come up 245# string nsd start in log. 246# $1 : logfilename that is watched. 247wait_nsd_up () { 248 wait_server_up "$1" " started (NSD " 249} 250 251# wait for server to go up, pass <logfilename> <string to watch> <badstr> 252# $1 : logfile 253# $2 : success string 254# $3 : failure string 255wait_server_up_or_fail () { 256 local MAX_UP_TRY=120 257 local WAIT_THRES=30 258 local try 259 for (( try=0 ; try <= $MAX_UP_TRY ; try++ )) ; do 260 if test -f $1 && grep -F "$2" $1 >/dev/null; then 261 echo "done on try $try" 262 break; 263 fi 264 if test -f $1 && grep -F "$3" $1 >/dev/null; then 265 echo "failed on try $try" 266 break; 267 fi 268 if test $try -eq $MAX_UP_TRY; then 269 echo "Server in $1 did not go up!" 270 cat $1 271 exit 1; 272 fi 273 if test $try -ge $WAIT_THRES; then 274 sleep 1 275 fi 276 done 277} 278 279# $1: zone 280# $2: serial to be expected 281# $3: server to query 282# $4: port 283# $5: # times to try (# seconds dig is ran) 284wait_for_soa_serial () { 285 TS_START=`date +%s` 286 for i in `seq 1 $5` 287 do 288 SERIAL=`dig -p $4 @$3 $1 SOA +short | awk '{ print $3 }'` 289 if test "$?" != "0" 290 then 291 echo "** \"dig -p $4 @$3 $1 SOA +short\" failed!" 292 return 1 293 fi 294 if test "$SERIAL" = "$2" 295 then 296 TS_END=`date +%s` 297 echo "*** Serial $2 was seen in $i tries (`expr $TS_END - $TS_START`) seconds" 298 return 0 299 fi 300 sleep 1 301 done 302 echo "** Serial $2 was not seen in $5 tries (did see: $SERIAL)" 303 return 1 304} 305 306# kill a pid, make sure and wait for it to go down. 307# $1 : pid to kill 308kill_pid () { 309 local MAX_DOWN_TRY=120 310 local WAIT_THRES=30 311 local try 312 kill $1 313 sleep .001 314 for (( try=0 ; try <= $MAX_DOWN_TRY ; try++ )) ; do 315 if kill -0 $1 >/dev/null 2>&1; then 316 : 317 else 318 #echo "done on try $try" 319 break; 320 fi 321 if test $try -eq $MAX_DOWN_TRY; then 322 echo "Server in $1 did not go down! Send SIGKILL" 323 kill -9 $1 >/dev/null 2>&1 324 fi 325 if test $try -ge $WAIT_THRES; then 326 sleep 1 327 else 328 sleep .01 329 fi 330 # re-send the signal 331 kill $1 >/dev/null 2>&1 332 done 333 return 0 334} 335 336# set doxygen path, so that make doc can find doxygen 337set_doxygen_path () { 338 if test -x '$HOME/bin/doxygen'; then 339 export PATH="$HOME/bin:$PATH" 340 fi 341} 342 343# get number of cpus in system 344cpu_count() 345{ 346 local sys=$(uname -s) 347 if [ "${sys}" = "Linux" ]; then 348 nproc 349 elif [ "${sys}" = "FreeBSD" ]; then 350 sysctl -n hw.ncpu 351 fi 352} 353 354# get cpu affinity list for process 355# $1 : pid 356process_cpu_list() { 357 local pid=${1} 358 local sys=$(uname -s) 359 360 if [ "${sys}" = "Linux" ]; then 361 local defl=$(taskset -pc ${pid} | sed -n -e 's/^.*: //p' | head -n 1) 362 elif [ "${sys}" = "FreeBSD" ]; then 363 local defl=$(cpuset -g -p ${pid} | sed -n -e 's/^.*: //p' | head -n 1) 364 fi 365 366 if [ -n "${defl}" ]; then 367 local infl 368 defl=$(echo "${defl}" | sed -e 's/,/ /g') 369 for i in ${defl}; do 370 rng=$(echo "${i}-${i}" | sed -e 's/^\([0-9]*\)-\([0-9]*\).*$/\1 \2/') 371 infl="${infl} $(seq -s ' ' ${rng})" 372 done 373 infl=$(echo ${infl} | sed -e 's/ */ /' -e 's/^ *//') 374 echo "${infl}" 375 fi 376} 377 378# 379# 380kill_from_pidfile() { 381 local pidfile="$1" 382 if test -f "$pidfile"; then 383 local pid=`head -n 1 "$pidfile"` 384 if test ! -z "$pid"; then 385 kill_pid "$pid" 386 fi 387 fi 388} 389 390# Print the current test step in the output 391teststep () { 392 echo 393 echo "STEP [ $1 ]" 394} 395