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