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