# vim: filetype=sh # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)logapi.kshlib 1.2 07/03/14 SMI" # # # This is a ksh function library. It is intended to be sourced into # other ksh scripts and not executed directly. # . ${STF_SUITE}/include/stf.shlib # # Send a debug message to stderr, if $STF_DEBUG set. # function log_debug { [ -z "$STF_DEBUG" ] && return echo "$*" >&2 } # Output an assertion # # $@ - assertion text function log_assert { _printline ASSERTION: "$@" } # Output a comment # # $@ - comment text function log_note { _printline NOTE: "$@" } # Execute a positive test and exit $STF_FAIL is test fails # # $@ - command to execute function log_must { log_pos "$@" (( $? != 0 )) && log_fail } # Execute a command that must exit $1 # # $@ - command to execute function log_mustbe { typeset exitcode_wanted=$1 shift log_cmd "$@" (( $? != $exitcode_wanted )) && log_fail } # Execute a negative test and exit $STF_FAIL if test passes # # $@ - command to execute function log_mustnot { log_neg "$@" (( $? != 0 )) && log_fail } # Execute a command that should only be logged if it fails. # # $@ - command to execute function log_onfail { eval $@ typeset status=$? [ $status -eq 0 ] && return _printerror "$@" "unexpectedly exited $status" } # Execute and print command with status where success equals non-zero result # or output includes expected keyword # # $2-$@ - command to execute # # Summary: execute $@. Return 1 if any of the following hold: # 1) The command exited 0, 127, 138, or 139 # 2) The command's stderr included "internal error" or # "assertion failed" # # return 0 if command fails, or the output contains the keyword expected, # return 1 otherwise function log_neg { typeset out="" typeset logfile="$TMPDIR/log.$$" typeset ret=1 while [[ -e $logfile ]]; do logfile="$logfile.$$" done "$@" 2>$logfile typeset status=$? out="/bin/cat $logfile" # unexpected status if (( $status == 0 )); then print -u2 $($out) _printerror "$@" "unexpectedly exited $status" # missing binary elif (( $status == 127 )); then print -u2 $($out) _printerror "$@" "unexpectedly exited $status (File not found)" # bus error - core dump elif (( $status == 138 )); then print -u2 $($out) _printerror "$@" "unexpectedly exited $status (Bus Error)" # segmentation violation - core dump elif (( $status == 139 )); then print -u2 $($out) _printerror "$@" "unexpectedly exited $status (SEGV)" else $out | /usr/bin/egrep -i "internal error|assertion failed" \ > /dev/null 2>&1 # internal error or assertion failed if (( $? == 0 )); then print -u2 $($out) _printerror "$@" "internal error or assertion failure" \ " exited $status" else ret=0 fi if (( $ret == 0 )); then [[ -n $LOGAPI_DEBUG ]] && print $($out) _printsuccess "$@" "exited $status" fi fi _recursive_output $logfile "false" return $ret } # Execute and print command; unconditionally return its exit code. # Useful for code that needs to do more specialized exit status filtering. function log_cmd { typeset logfile="$TMPDIR/log.$$" while [[ -e $logfile ]]; do logfile="$logfile.$$" done "$@" 2>$logfile typeset status=$? _printline "EXECUTED (exited $status): $@" _recursive_output $logfile "false" return $status } # Execute and print command with status where success equals zero result # # $@ command to execute # # Summary: run $@. return 1 if its exit status was nonzero or if it printed # "internal error" or "assertion failed" to stderr. # print stderr on failure or if LOGAPI_DEBUG is set. # # return command exit status function log_pos { typeset out="" typeset logfile="$TMPDIR/log.$$" while [[ -e $logfile ]]; do logfile="$logfile.$$" done "$@" 2>$logfile typeset status=$? out="/bin/cat $logfile" if (( $status != 0 )) ; then print -u2 $($out) _printerror "$@" "exited $status" else $out | /usr/bin/egrep -i "internal error|assertion failed" \ > /dev/null 2>&1 # internal error or assertion failed if [[ $? -eq 0 ]]; then print -u2 $($out) _printerror "$@" "internal error or assertion failure" \ " exited $status" status=1 else [[ -n $LOGAPI_DEBUG ]] && print $($out) _printsuccess "$@" fi fi _recursive_output $logfile "false" return $status } # Set an exit handler # # $@ - function(s) to perform on exit function log_onexit { _CLEANUP="$@" } # # Exit functions # # Perform cleanup and exit $STF_PASS # # $@ - message text function log_pass { _endlog $STF_PASS "$@" } # Perform cleanup and exit $STF_FAIL # # $@ - message text function log_fail { _endlog $STF_FAIL "$@" } # Perform cleanup and exit $STF_UNRESOLVED # # $@ - message text function log_unresolved { _endlog $STF_UNRESOLVED "$@" } # Perform cleanup and exit $STF_NOTINUSE # # $@ - message text function log_notinuse { _endlog $STF_NOTINUSE "$@" } # Perform cleanup and exit $STF_UNSUPPORTED # # $@ - message text function log_unsupported { _endlog $STF_UNSUPPORTED "$@" } # Perform cleanup and exit $STF_UNTESTED # # $@ - message text function log_untested { _endlog $STF_UNTESTED "$@" } # Perform cleanup and exit $STF_UNINITIATED # # $@ - message text function log_uninitiated { _endlog $STF_UNINITIATED "$@" } # Perform cleanup and exit $STF_NORESULT # # $@ - message text function log_noresult { _endlog $STF_NORESULT "$@" } # Perform cleanup and exit $STF_WARNING # # $@ - message text function log_warning { _endlog $STF_WARNING "$@" } # Perform cleanup and exit $STF_TIMED_OUT # # $@ - message text function log_timed_out { _endlog $STF_TIMED_OUT "$@" } # Perform cleanup and exit $STF_OTHER # # $@ - message text function log_other { _endlog $STF_OTHER "$@" } # # Internal functions # # Perform cleanup and exit # # Summary: Runs any cleanup routine registered with log_onexit. Prints a # message and exits $1. Note: the _recursive_output does # nothing, because the rest of this api guarantees that the # logfile will not exist. # $1 - stf exit code # $2-$n - message text function _endlog { typeset logfile="$TMPDIR/log.$$" _recursive_output $logfile export STF_EXITCODE=$1 shift (( ${#@} > 0 )) && _printline "$@" if [[ -n $_CLEANUP ]] ; then typeset cleanup=$_CLEANUP log_onexit "" log_note "Performing local cleanup via log_onexit ($cleanup)" $cleanup fi exit $STF_EXITCODE } # Output a formatted line # # $@ - message text function _printline { print `/bin/date +%H:%M:%S` "$@" } # Output an error message # # $@ - message text function _printerror { _printline ERROR: "$@" } # Output a success message # # $@ - message text function _printsuccess { _printline SUCCESS: "$@" } # Output logfiles recursively # # $1 - start file # $2 - indicate whether output the start file itself, default as yes. function _recursive_output #logfile { typeset logfile=$1 while [[ -e $logfile ]]; do if [[ -z $2 || $logfile != $1 ]]; then /bin/cat $logfile fi /bin/rm -f $logfile logfile="$logfile.$$" done }