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