1#
2# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3# Use is subject to license terms.
4#
5
6#
7# This is free software; you can redistribute it and/or modify it
8# under the terms of the "Artistic License" which is located in the
9# file named "LICENSE.Artistic" which is included with this software.
10#
11
12#
13# This file was originally part of the "contrib" portion of the
14# TET3 test harness from The OpenGroup, originally found here:
15# http://tetworks.opengroup.org/tet/ or ftp://ftp.xopen.org/pub/TET3/
16# and later published in hg.opensolaris.org/hg/test-dev/stcnv-gate
17#
18# A build of that repository delivers this file as part of the
19# SUNWstc-tetlite package, which carries the "Artistic" license
20# referred to above.
21#
22
23#
24# The "Artistic License" places some restrictions on the kinds of
25# changes that may be made to this file.  The changes made here
26# relative to the original are "portability fixes" to allow these
27# functions to operate in the "test-runner" environment.
28#
29# The original from which this was derived can be found here:
30#   https://bitbucket.org/illumos/illumos-stc/
31# under the path:
32#   usr/src/tools/tet/contrib/ctitools/src/lib/ksh/ctiutils.ksh
33
34########################################################################
35#
36# NAME:		ctiutils.shlib
37#
38# SYNOPSIS:
39#	cti_assert assertion_number assertion_msg
40#	cti_report arg ...
41#	cti_pass
42#	cti_fail [msg ...]
43#	cti_unresolved [msg ...]
44#	cti_untested [msg ...]
45#	cti_unsupported [msg ...]
46#	cti_notinuse [msg ...]
47#	cti_pathtrace
48#	cti_checkpath expected-path-count
49#	cti_deleteall reason
50#	cti_reportfile path [title]
51#	cti_rmf [files...]
52#	cti_writefile path mode lines...
53#	cti_appendfile path mode lines...
54#	cti_execute [-c out|err] [-i input] result cmd [args...]
55#	cti_runexpect failtext command pattern action [pattern action ...]
56#	cti_expecttest failtext command pattern action [pattern action ...]
57#	cti_cancel test_num [msg ...] [test result]
58#	cti_cancelall [msg ...] [test result]
59#
60# DESCRIPTION:
61#	Common korn shell functions for tests.
62#
63#	cti_report() writes an informational line to the journal.
64#
65#	The functions cti_pass(), cti_fail(), cti_unresolved(),
66#	cti_untested(), cti_unsupported() and cti_notinuse() each
67#	registers the corresponding result code against the current test,
68#	and write any arguments to the execution results file, as a
69#	single line.
70#
71#	The cti_pathtrace() and cti_checkpath() are used in path tracing.
72#	cti_pathtrace() increments the variable pathok. cti_checkpath()
73#	checks the path tracing and registers a PASS result if
74#	appropriate.
75#
76#	cti_deleteall() cancels all tests in the current test case.
77#
78#	cti_reportfile() writes the contents of a file to the journal.
79#
80#	cti_rmf() removes files.
81#
82#	cti_writefile() writes to the contents of a file;
83#	cti_appendfile() appends to contents of a file.
84#
85#	cti_execute() executes a command.
86#
87#	cti_runexpect() runs the expect utility. cti_expecttest() is
88#	like cti_runexpect() except that it is written with path tracing
89#	and is designed to do the complete work of a test purpose.
90#       cti_runexpect() runs the expect utility. cti_expecttest() is
91#       like cti_runexpect() except that it is written with path tracing
92#       and is designed to do the complete work of a test purpose.
93#
94#       cti_cancel() cancels the dedicated test purpose in the current test
95#       case from execution with the test result that user gives. It will work
96#       in startup function.
97#
98#       cti_cancelall() cancels all tests in the current test case. It could
99#       be used in startup function to cancel the execution of test cases
100#       with the test result that user gives.
101#
102########################################################################
103
104#
105# cti_lf_checkargs() - check number of arguments passed to a shell function.
106#
107# Usage: cti_lf_checkargs argc expected-argc operator funcname
108#
109# operator can be EQ or GE.
110#
111# Returns 0 if the expected number of arguments were passed, non-zero
112# otherwise.
113#
114function cti_lf_checkargs
115{
116	typeset -i cti_lv_argc=$1
117	typeset -i cti_lv_expargc=$2
118	typeset cti_lv_op="$3"
119	typeset cti_lv_funcname="$4"
120
121	case "$cti_lv_op" in
122	EQ)
123		if test $cti_lv_argc -ne $cti_lv_expargc
124		then
125			cti_unresolved "Test coding error:" \
126				"$cti_lv_funcname() called with $cti_lv_argc" \
127				"args, need $cti_lv_expargc"
128			return 1
129		fi
130		;;
131	GE)
132		if test $cti_lv_argc -lt $cti_lv_expargc
133		then
134			cti_unresolved "Test coding error:" \
135				"$cti_lv_funcname() called with $cti_lv_argc" \
136				"args, need >= $cti_lv_expargc"
137			return 1
138		fi
139		;;
140	*)
141		cti_unresolved "Internal error: cti_lf_checkargs()" \
142			"called for $funcname() with operator $cti_lv_op"
143		return 1
144		;;
145	esac
146
147	return 0
148}
149
150#
151# cti_result() - register a result and write informational line to journal.
152#
153# Usage: cti_result result [msg ...]
154#
155# If the current test function is not a startup or cleanup, this routine
156# registers the specified result code for the current test. The remaining
157# arguments, if any, are written to the execution results file as a single
158# line.
159#
160# Modifications for test-runner:
161# Print the result and test name (in place of tet_result)
162# On failure, return non-zero to tell test-runner our status.
163#
164function cti_result
165{
166	typeset res
167	typeset -i rv=0
168
169	test $# -eq 0 && return
170	res=$1
171	shift
172
173	my_host=`hostname`
174	my_timestamp=`date | awk '{print $4}'`
175
176	test $# -gt 0 && print "$my_host $my_timestamp $@"
177
178	# Print the result and test name (as tet_result would)
179	print "$res: ${tc_id:-$(basename $0)}"
180
181	# Return non-zero for failures.  See codes in:
182	# test-runner/stf/include/stf.shlib
183	case "$res" in
184	PASS)
185		;;
186	FAIL)
187		rv=1
188		;;
189	UNRESOLVED)
190		rv=2
191		;;
192	NOTINUSE)
193		rv=3
194		;;
195	UNSUPPORTED)
196		rv=4
197		;;
198	UNTESTED)
199		rv=5
200		;;
201	UNINITIATED)
202		rv=6
203		;;
204	NORESULT)
205		rv=7
206		;;
207	WARNING)
208		rv=8
209		;;
210	TIMED_OUT)
211		rv=9
212		;;
213	*)
214		echo "cti_result: $res: unknown result code"
215		rv=10
216		;;
217	esac
218	return $rv
219}
220
221#
222# cti_report() - write an informational line to the journal
223#
224# Usage: cti_report arg ...
225#
226# Writes the arguments to the execution results file, as a single line.
227#
228function cti_report
229{
230	my_host=`hostname`
231	my_timestamp=`date | awk '{print $4}'`
232
233	print "$my_host $my_timestamp $@"
234}
235
236#
237# cti_assert() - write an Assert line to the journal
238#
239# Usage: cti_assert assertion_number assertion_msg
240#
241# Writes the arguments to the execution results file, as a single line.
242#
243function cti_assert
244{
245	cti_lf_checkargs $# 2 GE cti_assert || return 1
246
247	cti_report "ASSERT $1: $2"
248}
249
250#
251# cti_pass() - register a PASS result.
252#
253# Usage: cti_pass [msg ...]
254#
255function cti_pass
256{
257	cti_result PASS "$@"
258}
259
260#
261# cti_fail() - register a FAIL result.
262#
263# Usage: cti_fail [msg ...]
264#
265# Registers a FAIL result for the current test, and writes any arguments to
266# the execution results file, as a single line.
267#
268function cti_fail
269{
270	cti_result FAIL "$@"
271}
272
273#
274# cti_unresolved() - register an UNRESOLVED result.
275#
276# Usage: cti_unresolved [msg ...]
277#
278# Registers an UNRESOLVED result for the current test, and writes any arguments
279# to the execution results file, as a single line.
280#
281function cti_unresolved
282{
283	cti_result UNRESOLVED "$@"
284}
285
286
287#
288# cti_uninitiated() - register an UNINITIATED result.
289#
290# Usage: cti_uninitiated [msg ...]
291#
292# Registers an UNINITIATED result for the current test, and writes any arguments
293# to the execution results file, as a single line.
294#
295function cti_uninitiated
296{
297	cti_result UNINITIATED "$@"
298}
299
300#
301# cti_untested() - register an UNTESTED result.
302#
303# Usage: cti_untested [msg ...]
304#
305# Registers an UNTESTED result for the current test, and writes any arguments
306# to the execution results file, as a single line.
307#
308function cti_untested
309{
310	cti_result UNTESTED "$@"
311}
312
313#
314# cti_unsupported() - register an UNSUPPORTED result.
315#
316# Usage: cti_unsupported [msg ...]
317#
318# Registers an UNSUPPORTED result for the current test, and writes any
319# arguments to the execution results file, as a single line.
320#
321function cti_unsupported
322{
323	cti_result UNSUPPORTED "$@"
324}
325
326#
327# cti_notinuse() - register a NOTINUSE result.
328#
329# Usage: cti_notinuse [msg ...]
330#
331# Registers a NOTINUSE result for the current test, and writes any arguments
332# to the execution results file, as a single line.
333#
334function cti_notinuse
335{
336	cti_result NOTINUSE "$@"
337}
338
339#
340# cti_pathtrace() - increment path counter.
341#
342# Usage: cti_pathtrace
343#
344# Increments variable pathok. Like C macro PATH_TRACE.
345#
346function cti_pathtrace
347{
348	: $((pathok += 1))
349}
350
351#
352# cti_checkpath() - check path tracing and register a PASS result.
353#
354# Usage: cti_checkpath expected-path-count
355#
356# Like C macro PATH_XS_RPT().
357#
358function cti_checkpath
359{
360	cti_lf_checkargs $# 1 EQ cti_checkpath || return
361
362	if test $pathok -eq $1
363	then
364		cti_pass
365	else
366		cti_unresolved "Path tracing error: path counter $pathok," \
367			"expecting $1"
368	fi
369}
370
371#
372# cti_deleteall() - cancel all tests.
373#
374# Usage: cti_deleteall reason
375#
376# Cancels all tests
377#
378function cti_deleteall
379{
380	typeset cti_lv_ic
381	typeset cti_lv_tp
382
383	test $# -eq 0 && return
384
385	for cti_lv_ic in $iclist
386	do
387		for cti_lv_tp in `eval echo \\$$cti_lv_ic`
388		do
389			if test -n "$cti_lv_tp"
390			then
391				echo "Deleted test: $cti_lv_tp" "$@"
392			fi
393		done
394	done
395}
396
397#
398# cti_reportfile() - write the contents of a file to the journal.
399#
400# Usage: cti_reportfile path [title]
401#
402# Writes the contents of the file specified by path to the execution results
403# file, line by line.
404#
405function cti_reportfile
406{
407	typeset cti_lv_path=$1
408	typeset cti_lv_title="${2:-$cti_lv_path}"
409	typeset cti_lv_line
410
411	cti_lf_checkargs $# 1 GE cti_reportfile || return
412
413	cti_report "+++ $cti_lv_title +++"
414
415	/usr/bin/cat $cti_lv_path
416
417	cti_report "+++ end +++"
418	cti_report " "
419}
420
421#
422# cti_rmf() - remove files.
423#
424# Usage: cti_rmf [files...]
425#
426# Calls "rm -f" to remove the files, and verifies that they have been removed.
427#
428# Returns 0 on success, non-zero if any of the files could not be removed.
429#
430function cti_rmf
431{
432	typeset cti_lv_file
433
434	for cti_lv_file in "$@"
435	do
436		rm -f "$cti_lv_file"
437
438		if test -f "$cti_lv_file"
439		then
440			cti_unresolved "Error removing file \"$cti_lv_file\""
441			return 1
442		fi
443	done
444
445	return 0
446}
447
448#
449# cti_writefile() - write contents of a file.
450#
451# Usage: cti_writefile path mode lines...
452#
453# Truncates the file specified by path and then writes the third and
454# subsequent arguments to the specified file as separate lines.
455#
456# Returns 0 on success, non-zero if any of the files could not be removed.
457#
458function cti_writefile
459{
460	cti_lf_checkargs $# 3 GE cti_writefile || return 1
461
462	cti_rmf "$1" || return 1
463	cti_appendfile "$@"
464}
465
466#
467# cti_appendfile() - append to contents of a file.
468#
469# Usage: cti_appendfile path mode lines...
470#
471# Appends the third and subsequent arguments to the specified file as separate
472# lines.
473#
474# Returns 0 on success, non-zero if any of the files could not be removed.
475#
476function cti_appendfile
477{
478	typeset cti_lv_path="$1"
479	typeset cti_lv_mode="$2"
480	typeset cti_lv_line
481
482	cti_lf_checkargs $# 3 GE cti_appendfile || return 1
483	shift 2
484
485	for cti_lv_line in "$@"
486	do
487		echo "$cti_lv_line" >> "$cti_lv_path"
488
489		if [[ $? -ne 0 ]]
490		then
491			cti_unresolved \
492				"Error writing to file \"$cti_lv_path\""
493			return 1
494		fi
495	done
496
497	cti_execute UNRESOLVED chmod "$cti_lv_mode" "$cti_lv_path"
498	return $?
499}
500
501#
502# cti_execute() - execute a command
503#
504# Usage: cti_execute [-c out|err] [-i input] result cmd [args...]
505#
506# Executes a command. The standard output is redirected to the file cti_stdout
507# and the standard error is redirected to the file cti_stderr.
508#
509# If the command has a non-zero exit status, cti_execute() registers a result
510# code of `result'.
511#
512# Options:
513#	-c out|err	Check standard output/error. If anything is written to
514#			the specified output channel, a result code of `result'
515#			is registered and the output written to the journal.
516#			May have multiple -c options.
517#	-i input	Use -i as an input line to the command.
518#			May have multiple -i options.
519#
520# Returns 0 on success, non-zero on failure (returning the
521#  exit status from the command when possible).
522#
523function cti_execute
524{
525	typeset cti_lv_opt
526	typeset -i cti_lv_checkstdout=0
527	typeset -i cti_lv_checkstderr=0
528	typeset cti_lv_result
529	typeset -i cti_lv_status
530	typeset -i cti_lv_rv=0
531
532	# Remove files used for redirecting standard I/O.
533	cti_rmf cti_stdin cti_stdout cti_stderr || return 1
534
535	# Create (empty) files to take standard output and error so there are
536	# no problems later when we come to run the command.
537	touch cti_stdout cti_stderr
538
539	if [[ $? -ne 0 ]]
540	then
541		cti_unresolved "Error creating files cti_stdout and cti_stderr"
542		return 1
543	fi
544
545	# Parse command line options
546	while getopts "c:i:l:s:" cti_lv_opt
547	do
548		case $cti_lv_opt in
549		c)
550			case "$OPTARG" in
551			out|err)
552				eval cti_lv_checkstd$OPTARG=1
553				;;
554			*)
555				cti_unresolved "cti_execute() called with" \
556					"bad option argument -c $OPTARG"
557				return 1
558				;;
559			esac
560			;;
561		i)
562			echo "$OPTARG" >> cti_stdin
563			if [[ $? -ne 0 ]]
564			then
565				cti_unresolved "Error writing to cti_stdin"
566				return 1
567			fi
568			;;
569		*)
570			cti_unresolved "cti_execute() called with illegal" \
571				"option $cti_lv_opt"
572			return 1
573			;;
574		esac
575	done
576
577	shift $((OPTIND-1))
578
579	# Verify the correct number of arguments were passed.
580	cti_lf_checkargs $# 2 GE cti_execute || return 1
581
582	# First (non-option) argument is the result code to use if the command
583	# fails.
584	cti_lv_result="${1:-UNRESOLVED}"
585	shift
586
587	# Execute the command, redirecting standard input if required.
588	if test -f cti_stdin
589	then
590		eval "$@" < cti_stdin > cti_stdout 2> cti_stderr
591	else
592		eval "$@" > cti_stdout 2> cti_stderr
593	fi
594
595	cti_lv_status=$?
596
597	# Check the exit status of the command
598	if test $cti_lv_status -ne 0
599	then
600		if [[ "$cti_lv_result" = "CTI" ]]
601		then
602			cti_report CTI "Command \"$*\" failed "\
603				"with status $cti_lv_status"
604		else
605			cti_result "$cti_lv_result"\
606				"Command \"$*\" failed "\
607				"with status $cti_lv_status"
608			cti_lv_rv=$cti_lv_status
609		fi
610	fi
611
612	# Always log output of cti_execute_cmd
613	if [[ "$cti_lv_result" = "CTI" ]]
614	then
615
616		if test -s cti_stdout
617		then
618			cti_reportfile cti_stdout "Standard output from command \"$*\""
619		fi
620		if test -s cti_stderr
621		then
622			cti_reportfile cti_stderr "Standard error from command \"$*\""
623		fi
624		return $cti_lv_status
625	fi
626
627	# If cmd failed, or if "-c err", check standard error.
628	if test \( $cti_lv_rv -ne 0 -o $cti_lv_checkstderr -eq 1 \) \
629		-a -s cti_stderr
630	then
631		cti_result "$cti_lv_result" \
632			"Command \"$*\" produced standard error"
633		cti_reportfile cti_stderr "Standard error from command \"$*\""
634		[[ $cti_lv_rv = 0 ]] && cti_lv_rv=1
635	fi
636
637	#  If cmd failed, or if "-c out", check standard output.
638	if test \( $cti_lv_rv -ne 0 -o $cti_lv_checkstdout -eq 1 \) \
639		-a -s cti_stdout
640	then
641		cti_result "$cti_lv_result" \
642			"Command \"$*\" produced standard output"
643		cti_reportfile cti_stdout "Standard output from command \"$*\""
644		[[ $cti_lv_rv = 0 ]] && cti_lv_rv=1
645	fi
646
647	return $cti_lv_rv
648}
649
650#
651# Exit values for expect scripts.
652# N.B. Do not use 0, as expect uses this for e.g. syntax errors.
653#
654typeset -ri CTI_EXP_RV_TIMEDOUT=1
655typeset -ri CTI_EXP_RV_TESTFAIL=2
656typeset -ri CTI_EXP_RV_OK=3
657
658#
659# cti_runexpect() - run the expect utility.
660#
661# Usage: cti_runexpect failtext command pattern action [pattern action ...]
662#
663# Executes the expect utility using the command line specified in the second
664# argument. Generates a temporary expect script which is removed at the end of
665# the call. The arguments following the second are pattern-action pairs. The
666# pattern can be a regular expression or "CALL", which indicates the action is
667# simply a function call which is unconditionally executed at that point.
668#
669# The following expect functions are available:
670#
671#	startcritical	Indicates that failures from this point onwards
672#			constitute a test failure. In that case the
673#			``failtext'' argument is used to report the error
674#			message.
675#	endcritical	Indicates the end of the test failure section begun by
676#			startcritical.
677#	finish		Exit the expect script here - the test has passed.
678#
679# Returns 0 on success, non-zero on failure.
680#
681function cti_runexpect
682{
683	typeset -ri CTI_EXP_TIMEOUT=5
684	typeset -r cti_lv_expfile="./cti_$tc_id-$$.exp"
685	typeset cti_lv_failtext="$1"
686	typeset cti_lv_command="$2"
687	typeset -i cti_lv_rv=0
688	typeset cti_lv_dopt
689
690	# Verify the correct number of arguments were passed.
691	cti_lf_checkargs $# 4 GE cti_runexpect || return 1
692
693	shift 2
694
695	# Generate expect script.
696	{
697	echo "set STATUS_OK       $CTI_EXP_RV_OK"
698	echo "set STATUS_FAIL     $CTI_EXP_RV_TESTFAIL"
699	echo "set STATUS_TIMEDOUT $CTI_EXP_RV_TIMEDOUT"
700	echo ''
701        echo "set timeout $CTI_EXP_TIMEOUT"
702        echo 'set retval $STATUS_TIMEDOUT'
703	echo ''
704	echo 'eval spawn [lrange $argv 0 end]'
705	echo ''
706	echo 'proc startcritical {} {'
707	echo '	global retval'
708	echo '	global STATUS_FAIL'
709	echo '	set retval $STATUS_FAIL'
710	echo '}'
711	echo ''
712	echo 'proc endcritical {} {'
713	echo '	global retval'
714	echo '	global STATUS_TIMEDOUT'
715	echo '	set retval $STATUS_TIMEDOUT'
716	echo '}'
717	echo ''
718	echo 'proc finish {} {'
719	echo '	global STATUS_OK'
720	echo '	exit $STATUS_OK'
721	echo '}'
722
723	while test $# -gt 1
724	do
725		echo ''
726
727		if test "$1" = "CALL"
728		then
729			echo "$2"
730		else
731			echo 'expect {'
732			echo "	-re \"$1\" {"
733			echo "		$2 "
734			echo '	}'
735			echo '	timeout {'
736			echo '		exit $retval'
737			echo '	}'
738			echo '}'
739		fi
740
741		shift 2
742	done
743	} > $cti_lv_expfile
744
745	# Check that there were no errors writing to the script file.
746	if test $? -ne 0
747	then
748		cti_unresolved "Error writing expect script to file" \
749			"\"$cti_lv_expfile\""
750		return 1
751	fi
752
753	# If debug is on, turn on expect debug flag.
754	case "$CTI_SHELL_DEBUG" in
755	y*|Y*)
756		cti_lv_dopt='-d'
757		;;
758	esac
759
760	# Execute expect using generated script.
761	expect $cti_lv_dopt -f $cti_lv_expfile $cti_lv_command > cti_expout 2>&1
762	cti_lv_rv=$?
763
764	# If debug is on, save expect script and output, otherwise remove
765	# script.
766	case "$CTI_SHELL_DEBUG" in
767	y*|Y*)
768		cp cti_expout ${cti_lv_expfile%.exp}.out
769		cti_report "DEBUG: expect script is $PWD/$cti_lv_expfile," \
770			"expect output is in $PWD/${cti_lv_expfile%.exp}.out"
771		;;
772	*)
773		rm -f $cti_lv_expfile
774	esac
775
776	# Deal with return value from expect.
777	case $cti_lv_rv in
778	$CTI_EXP_RV_OK)
779		return 0
780		;;
781	$CTI_EXP_RV_TIMEDOUT)
782		cti_unresolved "Expect script timed-out during test setup"
783		;;
784	$CTI_EXP_RV_TESTFAIL)
785		cti_fail "$cti_lv_failtext"
786		;;
787	*)
788		cti_unresolved "Test coding error or expect bug:" \
789			"unexpected exit status $cti_lv_rv from expect script"
790		cti_reportfile cti_expout "Output from expect"
791		;;
792	esac
793
794	return 1
795}
796
797#
798# cti_expecttest() - run the expect utility.
799#
800# Usage: cti_expecttest failtext command pattern action [pattern action ...]
801#
802# Common test function for test purposes which use expect. Like cti_runexpect()
803# except that this is written with path tracing and is designed to do the
804# complete work of a test purpose.
805#
806function cti_expecttest
807{
808	# Verify the correct number of arguments were passed.
809	cti_lf_checkargs $# 4 GE cti_expecttest || return
810
811	# Use cti_runexpect() to execute expect utililty.
812	if cti_runexpect "$@"
813	then
814		cti_pathtrace
815	else
816		return
817	fi
818
819	cti_checkpath 1
820}
821
822function cti_execute_cmd
823{
824	cti_execute CTI "$@"
825}
826
827#
828# "private" functions for internal use by cti_cancel function
829# used to replace test purpose functions which will be canceled.
830#
831function cancel_ic {
832	cti_result $cticancel_result "$cticancel_msg"
833}
834
835#
836# cti_cancel() - cancel an individual test purpose.
837#
838# Usage: cti_cancel tp reason [test result]
839#
840# Cancels an individual test by replace the tp function with
841# cancel_ic function
842#
843function cti_cancel {
844	test $# -gt 3 && return
845	test_num=$1
846	cticancel_msg="$2"
847	cticancel_result=${3:-"UNSUPPORTED"}
848	typeset cti_lv_ic cti_lv_ic_mod
849	typeset cti_lv_tp
850
851	cti_report "Canceling test $test_num: $cticancel_msg"
852	#
853	# translate the ic and point the test purpose ic to
854	# cancel_ic function
855	#
856	for cti_lv_ic in $iclist
857	do
858		cti_lv_ic_mod=""
859		for cti_lv_tp in `eval echo \\$$cti_lv_ic`
860		do
861			if [ X"$cti_lv_tp" == X"$test_num" ]; then
862				cti_lv_ic_mod=$cti_lv_ic_mod" cancel_ic"
863			else
864				cti_lv_ic_mod=$cti_lv_ic_mod" $cti_lv_tp"
865			fi
866		done
867		eval "$cti_lv_ic=\"$cti_lv_ic_mod\""
868	done
869}
870
871#
872# cti_cancelall() - cancel all tests.
873#
874# Usage: cti_cancelall reason [test result]
875#
876# Cancels all tests by replace the tests functions with cancel_ic function
877#
878function cti_cancelall {
879	typeset cti_lv_ic
880	typeset cti_lv_tp
881	cticancel_msg=$1
882	cticancel_result=${2:-"UNSUPPORTED"}
883
884	test $# -eq 0 && return
885
886	for cti_lv_ic in $iclist
887	do
888		for cti_lv_tp in `eval echo \\$$cti_lv_ic`
889		do
890			cti_cancel $cti_lv_tp "$cticancel_msg" \
891			    $cticancel_result
892		done
893	done
894}
895