1# vim: filetype=sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22 23# 24# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26 27# 28# This is a ksh function library. It is intended to be sourced into 29# other ksh scripts and not executed directly. 30# 31 32. ${STF_SUITE}/include/stf.shlib 33 34# 35# Send a debug message to stderr, if $STF_DEBUG set. 36# 37function log_debug 38{ 39 [ -z "$STF_DEBUG" ] && return 40 echo "$*" >&2 41} 42 43# Output an assertion 44# 45# $@ - assertion text 46 47function log_assert 48{ 49 _printline ASSERTION: "$@" 50} 51 52# Output a comment 53# 54# $@ - comment text 55 56function log_note 57{ 58 _printline NOTE: "$@" 59} 60 61# Execute a positive test and exit $STF_FAIL is test fails 62# 63# $@ - command to execute 64 65function log_must 66{ 67 log_pos "$@" 68 (( $? != 0 )) && log_fail 69} 70 71# Execute a command that must exit $1 72# 73# $@ - command to execute 74function log_mustbe 75{ 76 typeset exitcode_wanted=$1 77 shift 78 79 log_cmd "$@" 80 (( $? != $exitcode_wanted )) && log_fail 81} 82 83# Execute a negative test and exit $STF_FAIL if test passes 84# 85# $@ - command to execute 86 87function log_mustnot 88{ 89 log_neg "$@" 90 (( $? != 0 )) && log_fail 91} 92 93# Execute a command that should only be logged if it fails. 94# 95# $@ - command to execute 96function log_onfail 97{ 98 eval $@ 99 typeset status=$? 100 [ $status -eq 0 ] && return 101 _printerror "$@" "unexpectedly exited $status" 102} 103 104# Execute and print command with status where success equals non-zero result 105# or output includes expected keyword 106# 107# $2-$@ - command to execute 108# 109# Summary: execute $@. Return 1 if any of the following hold: 110# 1) The command exited 0, 127, 138, or 139 111# 2) The command's stderr included "internal error" or 112# "assertion failed" 113# 114# return 0 if command fails, or the output contains the keyword expected, 115# return 1 otherwise 116 117function log_neg 118{ 119 typeset out="" 120 typeset logfile="$TMPDIR/log.$$" 121 typeset ret=1 122 123 while [[ -e $logfile ]]; do 124 logfile="$logfile.$$" 125 done 126 127 "$@" 2>$logfile 128 typeset status=$? 129 out="/bin/cat $logfile" 130 131 # unexpected status 132 if (( $status == 0 )); then 133 print -u2 $($out) 134 _printerror "$@" "unexpectedly exited $status" 135 # missing binary 136 elif (( $status == 127 )); then 137 print -u2 $($out) 138 _printerror "$@" "unexpectedly exited $status (File not found)" 139 # bus error - core dump 140 elif (( $status == 138 )); then 141 print -u2 $($out) 142 _printerror "$@" "unexpectedly exited $status (Bus Error)" 143 # segmentation violation - core dump 144 elif (( $status == 139 )); then 145 print -u2 $($out) 146 _printerror "$@" "unexpectedly exited $status (SEGV)" 147 else 148 $out | /usr/bin/egrep -i "internal error|assertion failed" \ 149 > /dev/null 2>&1 150 # internal error or assertion failed 151 if (( $? == 0 )); then 152 print -u2 $($out) 153 _printerror "$@" "internal error or assertion failure" \ 154 " exited $status" 155 else 156 ret=0 157 fi 158 159 if (( $ret == 0 )); then 160 [[ -n $LOGAPI_DEBUG ]] && print $($out) 161 _printsuccess "$@" "exited $status" 162 fi 163 fi 164 _recursive_output $logfile "false" 165 return $ret 166} 167 168# Execute and print command; unconditionally return its exit code. 169# Useful for code that needs to do more specialized exit status filtering. 170function log_cmd 171{ 172 typeset logfile="$TMPDIR/log.$$" 173 174 while [[ -e $logfile ]]; do 175 logfile="$logfile.$$" 176 done 177 178 "$@" 2>$logfile 179 typeset status=$? 180 _printline "EXECUTED (exited $status): $@" 181 _recursive_output $logfile "false" 182 return $status 183} 184 185# Execute and print command with status where success equals zero result 186# 187# $@ command to execute 188# 189# Summary: run $@. return 1 if its exit status was nonzero or if it printed 190# "internal error" or "assertion failed" to stderr. 191# print stderr on failure or if LOGAPI_DEBUG is set. 192# 193# return command exit status 194 195function log_pos 196{ 197 typeset out="" 198 typeset logfile="$TMPDIR/log.$$" 199 200 while [[ -e $logfile ]]; do 201 logfile="$logfile.$$" 202 done 203 204 "$@" 2>$logfile 205 typeset status=$? 206 out="/bin/cat $logfile" 207 208 if (( $status != 0 )) ; then 209 print -u2 $($out) 210 _printerror "$@" "exited $status" 211 else 212 $out | /usr/bin/egrep -i "internal error|assertion failed" \ 213 > /dev/null 2>&1 214 # internal error or assertion failed 215 if [[ $? -eq 0 ]]; then 216 print -u2 $($out) 217 _printerror "$@" "internal error or assertion failure" \ 218 " exited $status" 219 status=1 220 else 221 [[ -n $LOGAPI_DEBUG ]] && print $($out) 222 _printsuccess "$@" 223 fi 224 fi 225 _recursive_output $logfile "false" 226 return $status 227} 228 229# Set an exit handler 230# 231# $@ - function(s) to perform on exit 232 233function log_onexit 234{ 235 _CLEANUP="$@" 236} 237 238# 239# Exit functions 240# 241 242# Perform cleanup and exit $STF_PASS 243# 244# $@ - message text 245 246function log_pass 247{ 248 _endlog $STF_PASS "$@" 249} 250 251# Perform cleanup and exit $STF_FAIL 252# 253# $@ - message text 254 255function log_fail 256{ 257 _endlog $STF_FAIL "$@" 258} 259 260# Perform cleanup and exit $STF_UNRESOLVED 261# 262# $@ - message text 263 264function log_unresolved 265{ 266 _endlog $STF_UNRESOLVED "$@" 267} 268 269# Perform cleanup and exit $STF_NOTINUSE 270# 271# $@ - message text 272 273function log_notinuse 274{ 275 _endlog $STF_NOTINUSE "$@" 276} 277 278# Perform cleanup and exit $STF_UNSUPPORTED 279# 280# $@ - message text 281 282function log_unsupported 283{ 284 _endlog $STF_UNSUPPORTED "$@" 285} 286 287# Perform cleanup and exit $STF_UNTESTED 288# 289# $@ - message text 290 291function log_untested 292{ 293 _endlog $STF_UNTESTED "$@" 294} 295 296# Perform cleanup and exit $STF_UNINITIATED 297# 298# $@ - message text 299 300function log_uninitiated 301{ 302 _endlog $STF_UNINITIATED "$@" 303} 304 305# Perform cleanup and exit $STF_NORESULT 306# 307# $@ - message text 308 309function log_noresult 310{ 311 _endlog $STF_NORESULT "$@" 312} 313 314# Perform cleanup and exit $STF_WARNING 315# 316# $@ - message text 317 318function log_warning 319{ 320 _endlog $STF_WARNING "$@" 321} 322 323# Perform cleanup and exit $STF_TIMED_OUT 324# 325# $@ - message text 326 327function log_timed_out 328{ 329 _endlog $STF_TIMED_OUT "$@" 330} 331 332# Perform cleanup and exit $STF_OTHER 333# 334# $@ - message text 335 336function log_other 337{ 338 _endlog $STF_OTHER "$@" 339} 340 341# 342# Internal functions 343# 344 345# Perform cleanup and exit 346# 347# Summary: Runs any cleanup routine registered with log_onexit. Prints a 348# message and exits $1. Note: the _recursive_output does 349# nothing, because the rest of this api guarantees that the 350# logfile will not exist. 351# $1 - stf exit code 352# $2-$n - message text 353 354function _endlog 355{ 356 typeset logfile="$TMPDIR/log.$$" 357 _recursive_output $logfile 358 359 export STF_EXITCODE=$1 360 shift 361 (( ${#@} > 0 )) && _printline "$@" 362 if [[ -n $_CLEANUP ]] ; then 363 typeset cleanup=$_CLEANUP 364 log_onexit "" 365 log_note "Performing local cleanup via log_onexit ($cleanup)" 366 $cleanup 367 fi 368 exit $STF_EXITCODE 369} 370 371# Output a formatted line 372# 373# $@ - message text 374 375function _printline 376{ 377 print `/bin/date +%H:%M:%S` "$@" 378} 379 380# Output an error message 381# 382# $@ - message text 383 384function _printerror 385{ 386 _printline ERROR: "$@" 387} 388 389# Output a success message 390# 391# $@ - message text 392 393function _printsuccess 394{ 395 _printline SUCCESS: "$@" 396} 397 398# Output logfiles recursively 399# 400# $1 - start file 401# $2 - indicate whether output the start file itself, default as yes. 402 403function _recursive_output #logfile 404{ 405 typeset logfile=$1 406 407 while [[ -e $logfile ]]; do 408 if [[ -z $2 || $logfile != $1 ]]; then 409 /bin/cat $logfile 410 fi 411 /bin/rm -f $logfile 412 logfile="$logfile.$$" 413 done 414} 415