xref: /freebsd/tests/sys/cddl/zfs/include/logapi.kshlib (revision 069ac18495ad8fde2748bc94b0f80a50250bb01d)
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