1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21 22# 23# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26# Copyright (c) 2012, 2016 by Delphix. All rights reserved. 27# 28 29. ${STF_TOOLS}/include/stf.shlib 30 31# Output an assertion 32# 33# $@ - assertion text 34 35function log_assert 36{ 37 _printline ASSERTION: "$@" 38} 39 40# Output a comment 41# 42# $@ - comment text 43 44function log_note 45{ 46 _printline NOTE: "$@" 47} 48 49# Execute and print command with status where success equals non-zero result 50# 51# $@ - command to execute 52# 53# return 0 if command fails, otherwise return 1 54 55function log_neg 56{ 57 log_neg_expect "" "$@" 58 return $? 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 negative test and exit $STF_FAIL if test passes 72# 73# $@ - command to execute 74 75function log_mustnot 76{ 77 log_neg "$@" 78 (( $? != 0 )) && log_fail 79} 80 81# Execute a positive test but retry the command on failure if the output 82# matches an expected pattern. Otherwise behave like log_must and exit 83# $STF_FAIL is test fails. 84# 85# $1 - retry keyword 86# $2 - retry attempts 87# $3-$@ - command to execute 88# 89function log_must_retry 90{ 91 typeset out="" 92 typeset logfile="/tmp/log.$$" 93 typeset status=1 94 typeset expect=$1 95 typeset retry=$2 96 typeset delay=1 97 shift 2 98 99 while [[ -e $logfile ]]; do 100 logfile="$logfile.$$" 101 done 102 103 while (( $retry > 0 )); do 104 "$@" 2>$logfile 105 status=$? 106 out="cat $logfile" 107 108 if (( $status == 0 )); then 109 $out | egrep -i "internal error|assertion failed" \ 110 > /dev/null 2>&1 111 # internal error or assertion failed 112 if [[ $? -eq 0 ]]; then 113 print -u2 $($out) 114 _printerror "$@" "internal error or" \ 115 " assertion failure exited $status" 116 status=1 117 else 118 [[ -n $LOGAPI_DEBUG ]] && print $($out) 119 _printsuccess "$@" 120 fi 121 break 122 else 123 $out | grep -i "$expect" > /dev/null 2>&1 124 if (( $? == 0 )); then 125 print -u2 $($out) 126 _printerror "$@" "Retry in $delay seconds" 127 sleep $delay 128 129 (( retry=retry - 1 )) 130 (( delay=delay * 2 )) 131 else 132 break; 133 fi 134 fi 135 done 136 137 if (( $status != 0 )) ; then 138 print -u2 $($out) 139 _printerror "$@" "exited $status" 140 fi 141 142 _recursive_output $logfile "false" 143 return $status 144} 145 146# Execute a positive test and exit $STF_FAIL is test fails after being 147# retried up to 5 times when the command returns the keyword "busy". 148# 149# $@ - command to execute 150function log_must_busy 151{ 152 log_must_retry "busy" 5 "$@" 153 (( $? != 0 )) && log_fail 154} 155 156# Execute a negative test with keyword expected, and exit 157# $STF_FAIL if test passes 158# 159# $1 - keyword expected 160# $2-$@ - command to execute 161 162function log_mustnot_expect 163{ 164 log_neg_expect "$@" 165 (( $? != 0 )) && log_fail 166} 167 168# Execute and print command with status where success equals non-zero result 169# or output includes expected keyword 170# 171# $1 - keyword expected 172# $2-$@ - command to execute 173# 174# return 0 if command fails, or the output contains the keyword expected, 175# return 1 otherwise 176 177function log_neg_expect 178{ 179 typeset out="" 180 typeset logfile="/tmp/log.$$" 181 typeset ret=1 182 typeset expect=$1 183 shift 184 185 while [[ -e $logfile ]]; do 186 logfile="$logfile.$$" 187 done 188 189 "$@" 2>$logfile 190 typeset status=$? 191 out="/usr/bin/cat $logfile" 192 193 # unexpected status 194 if (( $status == 0 )); then 195 print -u2 $($out) 196 _printerror "$@" "unexpectedly exited $status" 197 # missing binary 198 elif (( $status == 127 )); then 199 print -u2 $($out) 200 _printerror "$@" "unexpectedly exited $status (File not found)" 201 # bus error - core dump 202 elif (( $status == 138 )); then 203 print -u2 $($out) 204 _printerror "$@" "unexpectedly exited $status (Bus Error)" 205 # segmentation violation - core dump 206 elif (( $status == 139 )); then 207 print -u2 $($out) 208 _printerror "$@" "unexpectedly exited $status (SEGV)" 209 else 210 $out | /usr/bin/egrep -i "internal error|assertion failed" \ 211 > /dev/null 2>&1 212 # internal error or assertion failed 213 if (( $? == 0 )); then 214 print -u2 $($out) 215 _printerror "$@" "internal error or assertion failure" \ 216 " exited $status" 217 elif [[ -n $expect ]] ; then 218 $out | /usr/bin/grep -i "$expect" > /dev/null 2>&1 219 if (( $? == 0 )); then 220 ret=0 221 else 222 print -u2 $($out) 223 _printerror "$@" "unexpectedly exited $status" 224 fi 225 else 226 ret=0 227 fi 228 229 if (( $ret == 0 )); then 230 [[ -n $LOGAPI_DEBUG ]] && print $($out) 231 _printsuccess "$@" "exited $status" 232 fi 233 fi 234 _recursive_output $logfile "false" 235 return $ret 236} 237 238# Execute and print command with status where success equals zero result 239# 240# $@ command to execute 241# 242# return command exit status 243 244function log_pos 245{ 246 typeset out="" 247 typeset logfile="/tmp/log.$$" 248 249 while [[ -e $logfile ]]; do 250 logfile="$logfile.$$" 251 done 252 253 "$@" 2>$logfile 254 typeset status=$? 255 out="/usr/bin/cat $logfile" 256 257 if (( $status != 0 )) ; then 258 print -u2 $($out) 259 _printerror "$@" "exited $status" 260 else 261 $out | /usr/bin/egrep -i "internal error|assertion failed" \ 262 > /dev/null 2>&1 263 # internal error or assertion failed 264 if [[ $? -eq 0 ]]; then 265 print -u2 $($out) 266 _printerror "$@" "internal error or assertion failure" \ 267 " exited $status" 268 status=1 269 else 270 [[ -n $LOGAPI_DEBUG ]] && print $($out) 271 _printsuccess "$@" 272 fi 273 fi 274 _recursive_output $logfile "false" 275 return $status 276} 277 278# Set an exit handler 279# 280# $@ - function(s) to perform on exit 281 282function log_onexit 283{ 284 _CLEANUP="$@" 285} 286 287# 288# Exit functions 289# 290 291# Perform cleanup and exit $STF_PASS 292# 293# $@ - message text 294 295function log_pass 296{ 297 _endlog $STF_PASS "$@" 298} 299 300# Perform cleanup and exit $STF_FAIL 301# 302# $@ - message text 303 304function log_fail 305{ 306 _endlog $STF_FAIL "$@" 307} 308 309# Perform cleanup and exit $STF_UNRESOLVED 310# 311# $@ - message text 312 313function log_unresolved 314{ 315 _endlog $STF_UNRESOLVED "$@" 316} 317 318# Perform cleanup and exit $STF_NOTINUSE 319# 320# $@ - message text 321 322function log_notinuse 323{ 324 _endlog $STF_NOTINUSE "$@" 325} 326 327# Perform cleanup and exit $STF_UNSUPPORTED 328# 329# $@ - message text 330 331function log_unsupported 332{ 333 _endlog $STF_UNSUPPORTED "$@" 334} 335 336# Perform cleanup and exit $STF_UNTESTED 337# 338# $@ - message text 339 340function log_untested 341{ 342 _endlog $STF_UNTESTED "$@" 343} 344 345# Perform cleanup and exit $STF_UNINITIATED 346# 347# $@ - message text 348 349function log_uninitiated 350{ 351 _endlog $STF_UNINITIATED "$@" 352} 353 354# Perform cleanup and exit $STF_NORESULT 355# 356# $@ - message text 357 358function log_noresult 359{ 360 _endlog $STF_NORESULT "$@" 361} 362 363# Perform cleanup and exit $STF_WARNING 364# 365# $@ - message text 366 367function log_warning 368{ 369 _endlog $STF_WARNING "$@" 370} 371 372# Perform cleanup and exit $STF_TIMED_OUT 373# 374# $@ - message text 375 376function log_timed_out 377{ 378 _endlog $STF_TIMED_OUT "$@" 379} 380 381# Perform cleanup and exit $STF_OTHER 382# 383# $@ - message text 384 385function log_other 386{ 387 _endlog $STF_OTHER "$@" 388} 389 390# 391# Internal functions 392# 393 394# Execute custom callback scripts on test failure 395# 396# callback script paths are stored in TESTFAIL_CALLBACKS, delimited by ':'. 397 398function _execute_testfail_callbacks 399{ 400 typeset callback 401 402 print "$TESTFAIL_CALLBACKS:" | while read -d ":" callback; do 403 if [[ -n "$callback" ]] ; then 404 log_note "Performing test-fail callback ($callback)" 405 $callback 406 fi 407 done 408} 409 410# Perform cleanup and exit 411# 412# $1 - stf exit code 413# $2-$n - message text 414 415function _endlog 416{ 417 typeset logfile="/tmp/log.$$" 418 _recursive_output $logfile 419 420 if [[ $1 == $STF_FAIL ]] ; then 421 _execute_testfail_callbacks 422 fi 423 424 if [[ -n $_CLEANUP ]] ; then 425 typeset cleanup=$_CLEANUP 426 log_onexit "" 427 log_note "Performing local cleanup via log_onexit ($cleanup)" 428 $cleanup 429 fi 430 typeset exitcode=$1 431 shift 432 (( ${#@} > 0 )) && _printline "$@" 433 exit $exitcode 434} 435 436# Output a formatted line 437# 438# $@ - message text 439 440function _printline 441{ 442 print "$@" 443} 444 445# Output an error message 446# 447# $@ - message text 448 449function _printerror 450{ 451 _printline ERROR: "$@" 452} 453 454# Output a success message 455# 456# $@ - message text 457 458function _printsuccess 459{ 460 _printline SUCCESS: "$@" 461} 462 463# Output logfiles recursively 464# 465# $1 - start file 466# $2 - indicate whether output the start file itself, default as yes. 467 468function _recursive_output #logfile 469{ 470 typeset logfile=$1 471 472 while [[ -e $logfile ]]; do 473 if [[ -z $2 || $logfile != $1 ]]; then 474 /usr/bin/cat $logfile 475 fi 476 /usr/bin/rm -f $logfile 477 logfile="$logfile.$$" 478 done 479} 480