1#!/bin/bash
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2012 (c), Joyent, Inc.
15#
16
17#
18# mdb test driver
19#
20unalias -a
21shopt -s xpg_echo
22#set -o xtrace
23
24mt_arg0=$(basename $0)
25mt_ksh="/usr/bin/ksh"
26mt_mdb="/usr/bin/mdb"
27mt_outdir=
28mt_keep=
29mt_all=
30mt_tests=
31mt_tnum=0
32mt_tfail=0
33mt_tsuc=0
34
35function usage
36{
37	local msg="$*"
38	[[ -z "$msg" ]] || echo "$msg" 2>&1
39	cat <<USAGE >&2
40Usage: $mt_arg0  [ -o dir ] [ -k ] [ -m executable ] [ -a | test ... ]
41
42	-o dir		Sets 'dir' as the output directory
43	-a		Runs all tests, ignores tests passed in
44	-k		Keep output from all tests, not just failures
45	-m 		mdb binary to test
46USAGE
47	exit 2
48}
49
50function fatal
51{
52	local msg="$*"
53	[[ -z "$msg" ]] && msg="failed"
54	echo "$mt_arg0: $msg" >&2
55	exit 1
56}
57
58function setup_outdir
59{
60	mt_outdir="$mt_outdir/$mt_arg0.$$"
61	mkdir -p $mt_outdir || fatal "failed to make output dir $mt_outdir"
62}
63
64function run_single
65{
66	local name=$1
67	local expect base ext exe command odir res reason input
68
69	[[ -z "$name" ]] && fail "missing test to run"
70	base=${name##*/}
71	ext=${base##*.}
72	expect=${base%%.*}
73	odir="$mt_outdir/current"
74	[[ -z "$ext" ]] && fatal "found test without ext: $name"
75	[[ -z "$expect" ]] && fatal "found test without prefix: $name"
76
77	case "$ext" in
78	"ksh")
79		command="$mt_ksh $name"
80		;;
81	"mdb")
82		command="$mt_mdb"
83		input="$name"
84		;;
85	"out")
86		#
87		# This is the file format for checking output against.
88		#
89		return 0
90		;;
91	*)
92		echo "skipping test $name (unknown extensino)"
93		return 0
94		;;
95	esac
96
97	echo "Executing test $name ... \c"
98	mkdir -p "$odir" >/dev/null || fatal "can't make output directory"
99	if [[ -z "$input" ]]; then
100		MDB=$mt_mdb $command > "$odir/stdout" 2>"$odir/stderr"
101		res=$?
102	else
103		MDB=$mt_mdb $command < $input > "$odir/stdout" 2>"$odir/stderr"
104		res=$?
105	fi
106
107	if [[ -f "$name.out" ]] && ! diff "$name.out" "$odir/stdout" >/dev/null; then
108		cp $name.out $odir/$base.out
109		reason="stdout mismatch"
110	elif [[ "$expect" == "tst" && $res -ne 0 ]]; then
111		reason="test exited $res, not zero"
112	elif [[ "$expect" == "err" && $res -eq 0 ]]; then
113		reason="test exited $res, not non-zero"
114	fi
115
116	if [[ -n "$reason" ]]; then
117		echo "$reason"
118		((mt_tfail++))
119		mv "$odir" "$mt_outdir/failure.$mt_tfail" || fatal \
120		    "failed to move test output directory"
121		cp "$name" "$mt_outdir/failure.$mt_tfail/test" || fatal \
122		    "failed to copy test into output directory"
123	else
124		echo "passed"
125		((mt_tsuc++))
126		mv "$odir" "$mt_outdir/success.$mt_tsuc" || fatal \
127		    "failed to move test directory"	
128	fi
129
130	((mt_tnum++))
131}
132
133function run_all
134{
135	local tests t
136	
137	tests=$(find . -type f -name '[tst,err]*.*.[ksh,mdb]*')
138	for t in $tests; do
139		run_single $t
140	done
141}
142
143function welcome
144{
145	cat <<WELCOME
146Starting tests...
147mtest target: $mt_mdb
148output directory: $mt_outdir
149WELCOME
150}
151
152function cleanup
153{
154	[[ -n "$mt_keep" ]] && return
155	rm -rf "$mt_outdir"/success.* || fatal \
156	     "failed to remove successful test cases"
157	if [[ $mt_tfail -eq 0 ]]; then
158		rmdir "$mt_outdir" || fatal \
159		    "failed to remove test output directory"
160	fi
161}
162
163function goodbye
164{
165	cat <<EOF
166
167-------------
168Results
169-------------
170
171Tests passed: $mt_tsuc
172Tests failed: $mt_tfail
173Tests ran:    $mt_tnum
174
175EOF
176	if [[ $mt_tfail  -eq 0 ]]; then
177		echo "Congrats, mdb isn't completely broken, the tests pass".
178	else
179		echo "Some tests failed, you have some work to do."
180	fi
181}
182
183while getopts ":ahko:m:" c $@; do
184	case "$c" in
185	a)
186		mt_all="y"
187		;;
188	k)
189		mt_keep="y"
190		;;
191	m)
192		mt_mdb="$OPTARG"
193		;;
194	o)
195		mt_outdir="$OPTARG"
196		;;
197	h)
198		usage
199		;;
200	:)
201		usage "option requires an argument -- $OPTARG"
202		;;
203	*)
204		usage "invalid option -- $OPTARG"
205		;;
206	esac
207done
208
209shift $((OPTIND-1))
210
211[[ -z "$mt_all" && $# == 0 ]] && usage "no tests to run"
212
213[[ -x "$mt_mdb" ]] || fatal "unable to execute mdb binary: $mt_mdb"
214
215[[ -z "$mt_outdir" ]] && mt_outdir=/var/tmp
216
217setup_outdir
218welcome
219
220if [[ ! -z "$mt_all" ]]; then
221	run_all
222else
223	for t in $@; do
224		[[ -f $t ]] || fatal "cannot find test $t"
225		run_single $t		
226	done
227fi
228
229goodbye
230cleanup
231
232#
233# Exit 1 if we have tests that return non-zero
234#
235[[ $mt_tfai -eq 0 ]]
236