• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# Copyright (c) Linux Test Project, 2014-2017
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18#
19# Written by Cyril Hrubis <chrubis@suse.cz>
20#
21# This is a LTP test library for shell.
22#
23
24export TST_PASS=0
25export TST_FAIL=0
26export TST_BROK=0
27export TST_WARN=0
28export TST_CONF=0
29export TST_COUNT=1
30export TST_ITERATIONS=1
31
32. tst_ansi_color.sh
33
34tst_do_exit()
35{
36	local ret=0
37
38	if [ -n "$TST_SETUP_STARTED" -a -n "$TST_CLEANUP" -a \
39	     -z "$TST_NO_CLEANUP" ]; then
40		$TST_CLEANUP
41	fi
42
43	if [ "$TST_NEEDS_DEVICE" = 1 -a "$TST_DEVICE_FLAG" = 1 ]; then
44		if ! tst_device release "$TST_DEVICE"; then
45			tst_res TWARN "Failed to release device '$TST_DEVICE'"
46		fi
47	fi
48
49	if [ "$TST_NEEDS_TMPDIR" = 1 -a -n "$TST_TMPDIR" ]; then
50		cd "$LTPROOT"
51		rm -r "$TST_TMPDIR"
52	fi
53
54	if [ $TST_FAIL -gt 0 ]; then
55		ret=$((ret|1))
56	fi
57
58	if [ $TST_BROK -gt 0 ]; then
59		ret=$((ret|2))
60	fi
61
62	if [ $TST_WARN -gt 0 ]; then
63		ret=$((ret|4))
64	fi
65
66	if [ $TST_CONF -gt 0 ]; then
67		ret=$((ret|32))
68	fi
69
70	echo
71	echo "Summary:"
72	echo "passed   $TST_PASS"
73	echo "failed   $TST_FAIL"
74	echo "skipped  $TST_CONF"
75	echo "warnings $TST_WARN"
76
77	exit $ret
78}
79
80tst_inc_res()
81{
82	case "$1" in
83	TPASS) TST_PASS=$((TST_PASS+1));;
84	TFAIL) TST_FAIL=$((TST_FAIL+1));;
85	TBROK) TST_BROK=$((TST_BROK+1));;
86	TWARN) TST_WARN=$((TST_WARN+1));;
87	TCONF) TST_CONF=$((TST_CONF+1));;
88	TINFO) ;;
89	*) tst_brk TBROK "Invalid resm type '$1'";;
90	esac
91}
92
93tst_res()
94{
95	local res=$1
96	shift
97
98	tst_color_enabled
99	local color=$?
100
101	tst_inc_res "$res"
102
103	printf "$TCID $TST_COUNT "
104	tst_print_colored $res "$res: "
105	echo "$@"
106}
107
108tst_brk()
109{
110	local res=$1
111	shift
112
113	tst_res "$res" "$@"
114	tst_do_exit
115}
116
117ROD_SILENT()
118{
119	tst_rod $@ > /dev/null 2>&1
120	if [ $? -ne 0 ]; then
121		tst_brk TBROK "$@ failed"
122	fi
123}
124
125ROD()
126{
127	tst_rod "$@"
128	if [ $? -ne 0 ]; then
129		tst_brk TBROK "$@ failed"
130	fi
131}
132
133EXPECT_PASS()
134{
135	tst_rod "$@"
136	if [ $? -eq 0 ]; then
137		tst_res TPASS "$@ passed as expected"
138	else
139		tst_res TFAIL "$@ failed unexpectedly"
140	fi
141}
142
143EXPECT_FAIL()
144{
145	# redirect stderr since we expect the command to fail
146	tst_rod "$@" 2> /dev/null
147	if [ $? -ne 0 ]; then
148		tst_res TPASS "$@ failed as expected"
149	else
150		tst_res TFAIL "$@ passed unexpectedly"
151	fi
152}
153
154tst_umount()
155{
156	local device="$1"
157	local i=0
158
159	if ! grep -q "$device" /proc/mounts; then
160		tst_res TINFO "The $device is not mounted, skipping umount"
161		return
162	fi
163
164	while [ "$i" -lt 50 ]; do
165		if umount "$device" > /dev/null; then
166			return
167		fi
168
169		i=$((i+1))
170
171		tst_res TINFO "umount($device) failed, try $i ..."
172		tst_res TINFO "Likely gvfsd-trash is probing newly mounted "\
173		              "fs, kill it to speed up tests."
174
175		tst_sleep 100ms
176	done
177
178	tst_res TWARN "Failed to umount($device) after 50 retries"
179}
180
181tst_mkfs()
182{
183	local fs_type=$1
184	local device=$2
185	shift 2
186	local fs_opts="$@"
187
188	if [ -z "$fs_type" ]; then
189		tst_brk TBROK "No fs_type specified"
190	fi
191
192	if [ -z "$device" ]; then
193		tst_brk TBROK "No device specified"
194	fi
195
196	tst_res TINFO "Formatting $device with $fs_type extra opts='$fs_opts'"
197
198	ROD_SILENT mkfs.$fs_type $fs_opts $device
199}
200
201tst_check_cmds()
202{
203	local cmd
204	for cmd in $*; do
205		if ! command -v $cmd > /dev/null 2>&1; then
206			tst_brk TCONF "'$cmd' not found"
207		fi
208	done
209}
210
211tst_is_int()
212{
213	[ "$1" -eq "$1" ] 2>/dev/null
214	return $?
215}
216
217tst_usage()
218{
219	if [ -n "$TST_USAGE" ]; then
220		$TST_USAGE
221	else
222		echo "usage: $0"
223		echo "OPTIONS"
224	fi
225
226	echo "-h      Prints this help"
227	echo "-i n    Execute test n times"
228}
229
230tst_resstr()
231{
232	echo "$TST_PASS$TST_FAIL$TST_CONF"
233}
234
235tst_rescmp()
236{
237	local res=$(tst_resstr)
238
239	if [ "$1" = "$res" ]; then
240		tst_brk TBROK "Test didn't report any results"
241	fi
242}
243
244tst_run()
245{
246	local tst_i
247
248	if [ -n "$TST_TEST_PATH" ]; then
249		for tst_i in $(grep TST_ "$TST_TEST_PATH" | sed 's/.*TST_//; s/[="} \t\/:`].*//'); do
250			case "$tst_i" in
251			SETUP|CLEANUP|TESTFUNC|ID|CNT);;
252			OPTS|USAGE|PARSE_ARGS|POS_ARGS);;
253			NEEDS_ROOT|NEEDS_TMPDIR|NEEDS_DEVICE|DEVICE);;
254			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
255			*) tst_res TWARN "Reserved variable TST_$tst_i used!";;
256			esac
257		done
258	fi
259
260	local name
261
262	OPTIND=1
263
264	while getopts "hi:$TST_OPTS" name $TST_ARGS; do
265		case $name in
266		'h') tst_usage; exit 0;;
267		'i') TST_ITERATIONS=$OPTARG;;
268		'?') tst_usage; exit 2;;
269		*) $TST_PARSE_ARGS "$name" "$OPTARG";;
270		esac
271	done
272
273	if ! tst_is_int "$TST_ITERATIONS"; then
274		tst_brk TBROK "Expected number (-i) not '$TST_ITERATIONS'"
275	fi
276
277	if [ "$TST_ITERATIONS" -le 0 ]; then
278		tst_brk TBROK "Number of iterations (-i) must be > 0"
279	fi
280
281	if [ "$TST_NEEDS_ROOT" = 1 ]; then
282		if [ "$(id -ru)" != 0 ]; then
283			tst_brk TCONF "Must be super/root for this test!"
284		fi
285	fi
286
287	tst_check_cmds $TST_NEEDS_CMDS
288
289	if [ "$TST_NEEDS_TMPDIR" = 1 ]; then
290		if [ -z "$TMPDIR" ]; then
291			export TMPDIR="/tmp"
292		fi
293
294		TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX")
295
296		chmod 777 "$TST_TMPDIR"
297
298		TST_STARTWD=$(pwd)
299
300		cd "$TST_TMPDIR"
301	fi
302
303	if [ "$TST_NEEDS_DEVICE" = 1 ]; then
304		if [ -z ${TST_TMPDIR} ]; then
305			tst_brk "Use TST_NEEDS_TMPDIR must be set for TST_NEEDS_DEVICE"
306		fi
307
308		TST_DEVICE=$(tst_device acquire)
309
310		if [ -z "$TST_DEVICE" ]; then
311			tst_brk "Failed to acquire device"
312		fi
313
314		TST_DEVICE_FLAG=1
315	fi
316
317	if [ -n "$TST_NEEDS_MODULE" ]; then
318		for tst_module in "$TST_NEEDS_MODULE" \
319		                  "$LTPROOT/testcases/bin/$TST_NEEDS_MODULE" \
320		                  "$TST_STARTWD/$TST_NEEDS_MODULE"; do
321
322				if [ -f "$tst_module" ]; then
323					TST_MODPATH="$tst_module"
324					break
325				fi
326		done
327
328		if [ -z "$TST_MODPATH" ]; then
329			tst_brk TCONF "Failed to find module '$TST_NEEDS_MODULE'"
330		else
331			tst_res TINFO "Found module at '$TST_MODPATH'"
332		fi
333	fi
334
335	if [ -n "$TST_SETUP" ]; then
336		TST_SETUP_STARTED=1
337		$TST_SETUP
338	fi
339
340	#TODO check that test reports some results for each test function call
341	while [ $TST_ITERATIONS -gt 0 ]; do
342		if [ -n "$TST_CNT" ]; then
343			if type test1 > /dev/null 2>&1; then
344				for tst_i in $(seq $TST_CNT); do
345					local res=$(tst_resstr)
346					$TST_TESTFUNC$tst_i
347					tst_rescmp "$res"
348					TST_COUNT=$((TST_COUNT+1))
349				done
350			else
351				for tst_i in $(seq $TST_CNT); do
352					local res=$(tst_resstr)
353					$TST_TESTFUNC $tst_i
354					tst_rescmp "$res"
355					TST_COUNT=$((TST_COUNT+1))
356				done
357			fi
358		else
359			local res=$(tst_resstr)
360			$TST_TESTFUNC
361			tst_rescmp "$res"
362			TST_COUNT=$((TST_COUNT+1))
363		fi
364		TST_ITERATIONS=$((TST_ITERATIONS-1))
365	done
366
367	tst_do_exit
368}
369
370if TST_TEST_PATH=$(which $0) 2>/dev/null; then
371	if ! grep -q tst_run "$TST_TEST_PATH"; then
372		tst_brk TBROK "Test $0 must call tst_run!"
373	fi
374fi
375
376if [ -z "$TST_ID" ]; then
377	tst_brk TBROK "TST_ID is not defined"
378fi
379export TST_ID="$TST_ID"
380
381if [ -z "$TST_TESTFUNC" ]; then
382	tst_brk TBROK "TST_TESTFUNC is not defined"
383fi
384
385if [ -n "$TST_CNT" ]; then
386	if ! tst_is_int "$TST_CNT"; then
387		tst_brk TBROK "TST_CNT must be integer"
388	fi
389
390	if [ "$TST_CNT" -le 0 ]; then
391		tst_brk TBROK "TST_CNT must be > 0"
392	fi
393fi
394
395if [ -n "$TST_POS_ARGS" ]; then
396	if ! tst_is_int "$TST_POS_ARGS"; then
397		tst_brk TBROK "TST_POS_ARGS must be integer"
398	fi
399
400	if [ "$TST_POS_ARGS" -le 0 ]; then
401		tst_brk TBROK "TST_POS_ARGS must be > 0"
402	fi
403fi
404
405if [ -z "$LTPROOT" ]; then
406	export LTPROOT="$PWD"
407	export TST_DATAROOT="$LTPROOT/datafiles"
408else
409	export TST_DATAROOT="$LTPROOT/testcases/data/$TST_ID"
410fi
411
412TST_ARGS="$@"
413
414while getopts ":hi:$TST_OPTS" tst_name; do
415	case $tst_name in
416	'h') TST_PRINT_HELP=1;;
417	*);;
418	esac
419done
420
421shift $((OPTIND - 1))
422
423if [ -n "$TST_POS_ARGS" ]; then
424	if [ -z "$TST_PRINT_HELP" -a $# -ne "$TST_POS_ARGS" ]; then
425		tst_brk TBROK "Invalid number of positional paramters:"\
426			      "have ($@) $#, expected ${TST_POS_ARGS}"
427	fi
428else
429	if [ -z "$TST_PRINT_HELP" -a $# -ne 0 ]; then
430		tst_brk TBROK "Unexpected positional arguments '$@'"
431	fi
432fi
433