1#!/bin/bash
2# Copyright (C) 2017 Luis R. Rodriguez <[email protected]>
3#
4# This program is free software; you can redistribute it and/or modify it
5# under the terms of the GNU General Public License as published by the Free
6# Software Foundation; either version 2 of the License, or at your option any
7# later version; or, when distributed separately from the Linux kernel or
8# when incorporated into other software packages, subject to the following
9# license:
10#
11# This program is free software; you can redistribute it and/or modify it
12# under the terms of copyleft-next (version 0.3.1 or later) as published
13# at http://copyleft-next.org/.
14
15# This performs a series tests against the proc sysctl interface.
16
17# Kselftest framework requirement - SKIP code is 4.
18ksft_skip=4
19
20TEST_NAME="sysctl"
21TEST_DRIVER="test_${TEST_NAME}"
22TEST_DIR=$(dirname $0)
23TEST_FILE=$(mktemp)
24
25# This represents
26#
27# TEST_ID:TEST_COUNT:ENABLED:TARGET
28#
29# TEST_ID: is the test id number
30# TEST_COUNT: number of times we should run the test
31# ENABLED: 1 if enabled, 0 otherwise
32# TARGET: test target file required on the test_sysctl module
33#
34# Once these are enabled please leave them as-is. Write your own test,
35# we have tons of space.
36ALL_TESTS="0001:1:1:int_0001"
37ALL_TESTS="$ALL_TESTS 0002:1:1:string_0001"
38ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002"
39ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001"
40ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003"
41
42test_modprobe()
43{
44       if [ ! -d $DIR ]; then
45               echo "$0: $DIR not present" >&2
46               echo "You must have the following enabled in your kernel:" >&2
47               cat $TEST_DIR/config >&2
48               exit $ksft_skip
49       fi
50}
51
52function allow_user_defaults()
53{
54	if [ -z $DIR ]; then
55		DIR="/sys/module/test_sysctl/"
56	fi
57	if [ -z $DEFAULT_NUM_TESTS ]; then
58		DEFAULT_NUM_TESTS=50
59	fi
60	if [ -z $SYSCTL ]; then
61		SYSCTL="/proc/sys/debug/test_sysctl"
62	fi
63	if [ -z $PROD_SYSCTL ]; then
64		PROD_SYSCTL="/proc/sys"
65	fi
66	if [ -z $WRITES_STRICT ]; then
67		WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"
68	fi
69}
70
71function check_production_sysctl_writes_strict()
72{
73	echo -n "Checking production write strict setting ... "
74	if [ ! -e ${WRITES_STRICT} ]; then
75		echo "FAIL, but skip in case of old kernel" >&2
76	else
77		old_strict=$(cat ${WRITES_STRICT})
78		if [ "$old_strict" = "1" ]; then
79			echo "ok"
80		else
81			echo "FAIL, strict value is 0 but force to 1 to continue" >&2
82			echo "1" > ${WRITES_STRICT}
83		fi
84	fi
85
86	if [ -z $PAGE_SIZE ]; then
87		PAGE_SIZE=$(getconf PAGESIZE)
88	fi
89	if [ -z $MAX_DIGITS ]; then
90		MAX_DIGITS=$(($PAGE_SIZE/8))
91	fi
92	if [ -z $INT_MAX ]; then
93		INT_MAX=$(getconf INT_MAX)
94	fi
95	if [ -z $UINT_MAX ]; then
96		UINT_MAX=$(getconf UINT_MAX)
97	fi
98}
99
100test_reqs()
101{
102	uid=$(id -u)
103	if [ $uid -ne 0 ]; then
104		echo $msg must be run as root >&2
105		exit $ksft_skip
106	fi
107
108	if ! which perl 2> /dev/null > /dev/null; then
109		echo "$0: You need perl installed"
110		exit $ksft_skip
111	fi
112	if ! which getconf 2> /dev/null > /dev/null; then
113		echo "$0: You need getconf installed"
114		exit $ksft_skip
115	fi
116	if ! which diff 2> /dev/null > /dev/null; then
117		echo "$0: You need diff installed"
118		exit $ksft_skip
119	fi
120}
121
122function load_req_mod()
123{
124	if [ ! -d $DIR ]; then
125		if ! modprobe -q -n $TEST_DRIVER; then
126			echo "$0: module $TEST_DRIVER not found [SKIP]"
127			exit $ksft_skip
128		fi
129		modprobe $TEST_DRIVER
130		if [ $? -ne 0 ]; then
131			exit
132		fi
133	fi
134}
135
136reset_vals()
137{
138	VAL=""
139	TRIGGER=$(basename ${TARGET})
140	case "$TRIGGER" in
141		int_0001)
142			VAL="60"
143			;;
144		int_0002)
145			VAL="1"
146			;;
147		uint_0001)
148			VAL="314"
149			;;
150		string_0001)
151			VAL="(none)"
152			;;
153		*)
154			;;
155	esac
156	echo -n $VAL > $TARGET
157}
158
159set_orig()
160{
161	if [ ! -z $TARGET ] && [ ! -z $ORIG ]; then
162		if [ -f ${TARGET} ]; then
163			echo "${ORIG}" > "${TARGET}"
164		fi
165	fi
166}
167
168set_test()
169{
170	echo "${TEST_STR}" > "${TARGET}"
171}
172
173verify()
174{
175	local seen
176	seen=$(cat "$1")
177	if [ "${seen}" != "${TEST_STR}" ]; then
178		return 1
179	fi
180	return 0
181}
182
183verify_diff_w()
184{
185	echo "$TEST_STR" | diff -q -w -u - $1 > /dev/null
186	return $?
187}
188
189test_rc()
190{
191	if [[ $rc != 0 ]]; then
192		echo "Failed test, return value: $rc" >&2
193		exit $rc
194	fi
195}
196
197test_finish()
198{
199	set_orig
200	rm -f "${TEST_FILE}"
201
202	if [ ! -z ${old_strict} ]; then
203		echo ${old_strict} > ${WRITES_STRICT}
204	fi
205	exit $rc
206}
207
208run_numerictests()
209{
210	echo "== Testing sysctl behavior against ${TARGET} =="
211
212	rc=0
213
214	echo -n "Writing test file ... "
215	echo "${TEST_STR}" > "${TEST_FILE}"
216	if ! verify "${TEST_FILE}"; then
217		echo "FAIL" >&2
218		exit 1
219	else
220		echo "ok"
221	fi
222
223	echo -n "Checking sysctl is not set to test value ... "
224	if verify "${TARGET}"; then
225		echo "FAIL" >&2
226		exit 1
227	else
228		echo "ok"
229	fi
230
231	echo -n "Writing sysctl from shell ... "
232	set_test
233	if ! verify "${TARGET}"; then
234		echo "FAIL" >&2
235		exit 1
236	else
237		echo "ok"
238	fi
239
240	echo -n "Resetting sysctl to original value ... "
241	set_orig
242	if verify "${TARGET}"; then
243		echo "FAIL" >&2
244		exit 1
245	else
246		echo "ok"
247	fi
248
249	# Now that we've validated the sanity of "set_test" and "set_orig",
250	# we can use those functions to set starting states before running
251	# specific behavioral tests.
252
253	echo -n "Writing entire sysctl in single write ... "
254	set_orig
255	dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
256	if ! verify "${TARGET}"; then
257		echo "FAIL" >&2
258		rc=1
259	else
260		echo "ok"
261	fi
262
263	echo -n "Writing middle of sysctl after synchronized seek ... "
264	set_test
265	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
266	if ! verify "${TARGET}"; then
267		echo "FAIL" >&2
268		rc=1
269	else
270		echo "ok"
271	fi
272
273	echo -n "Writing beyond end of sysctl ... "
274	set_orig
275	dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
276	if verify "${TARGET}"; then
277		echo "FAIL" >&2
278		rc=1
279	else
280		echo "ok"
281	fi
282
283	echo -n "Writing sysctl with multiple long writes ... "
284	set_orig
285	(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
286		dd of="${TARGET}" bs=50 2>/dev/null
287	if verify "${TARGET}"; then
288		echo "FAIL" >&2
289		rc=1
290	else
291		echo "ok"
292	fi
293	test_rc
294}
295
296check_failure()
297{
298	echo -n "Testing that $1 fails as expected..."
299	reset_vals
300	TEST_STR="$1"
301	orig="$(cat $TARGET)"
302	echo -n "$TEST_STR" > $TARGET 2> /dev/null
303
304	# write should fail and $TARGET should retain its original value
305	if [ $? = 0 ] || [ "$(cat $TARGET)" != "$orig" ]; then
306		echo "FAIL" >&2
307		rc=1
308	else
309		echo "ok"
310	fi
311	test_rc
312}
313
314run_wideint_tests()
315{
316	# sysctl conversion functions receive a boolean sign and ulong
317	# magnitude; here we list the magnitudes we want to test (each of
318	# which will be tested in both positive and negative forms).  Since
319	# none of these values fit in 32 bits, writing them to an int- or
320	# uint-typed sysctl should fail.
321	local magnitudes=(
322		# common boundary-condition values (zero, +1, -1, INT_MIN,
323		# and INT_MAX respectively) if truncated to lower 32 bits
324		# (potential for being falsely deemed in range)
325		0x0000000100000000
326		0x0000000100000001
327		0x00000001ffffffff
328		0x0000000180000000
329		0x000000017fffffff
330
331		# these look like negatives, but without a leading '-' are
332		# actually large positives (should be rejected as above
333		# despite being zero/+1/-1/INT_MIN/INT_MAX in the lower 32)
334		0xffffffff00000000
335		0xffffffff00000001
336		0xffffffffffffffff
337		0xffffffff80000000
338		0xffffffff7fffffff
339	)
340
341	for sign in '' '-'; do
342		for mag in "${magnitudes[@]}"; do
343			check_failure "${sign}${mag}"
344		done
345	done
346}
347
348# Your test must accept digits 3 and 4 to use this
349run_limit_digit()
350{
351	echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ..."
352	reset_vals
353
354	LIMIT=$((MAX_DIGITS -1))
355	TEST_STR="3"
356	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
357		dd of="${TARGET}" 2>/dev/null
358
359	if ! verify "${TARGET}"; then
360		echo "FAIL" >&2
361		rc=1
362	else
363		echo "ok"
364	fi
365	test_rc
366
367	echo -n "Checking passing PAGE_SIZE of spaces fails on write ..."
368	reset_vals
369
370	LIMIT=$((MAX_DIGITS))
371	TEST_STR="4"
372	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
373		dd of="${TARGET}" 2>/dev/null
374
375	if verify "${TARGET}"; then
376		echo "FAIL" >&2
377		rc=1
378	else
379		echo "ok"
380	fi
381	test_rc
382}
383
384# You are using an int
385run_limit_digit_int()
386{
387	echo -n "Testing INT_MAX works ..."
388	reset_vals
389	TEST_STR="$INT_MAX"
390	echo -n $TEST_STR > $TARGET
391
392	if ! verify "${TARGET}"; then
393		echo "FAIL" >&2
394		rc=1
395	else
396		echo "ok"
397	fi
398	test_rc
399
400	echo -n "Testing INT_MAX + 1 will fail as expected..."
401	reset_vals
402	let TEST_STR=$INT_MAX+1
403	echo -n $TEST_STR > $TARGET 2> /dev/null
404
405	if verify "${TARGET}"; then
406		echo "FAIL" >&2
407		rc=1
408	else
409		echo "ok"
410	fi
411	test_rc
412
413	echo -n "Testing negative values will work as expected..."
414	reset_vals
415	TEST_STR="-3"
416	echo -n $TEST_STR > $TARGET 2> /dev/null
417	if ! verify "${TARGET}"; then
418		echo "FAIL" >&2
419		rc=1
420	else
421		echo "ok"
422	fi
423	test_rc
424}
425
426# You used an int array
427run_limit_digit_int_array()
428{
429	echo -n "Testing array works as expected ... "
430	TEST_STR="4 3 2 1"
431	echo -n $TEST_STR > $TARGET
432
433	if ! verify_diff_w "${TARGET}"; then
434		echo "FAIL" >&2
435		rc=1
436	else
437		echo "ok"
438	fi
439	test_rc
440
441	echo -n "Testing skipping trailing array elements works ... "
442	# Do not reset_vals, carry on the values from the last test.
443	# If we only echo in two digits the last two are left intact
444	TEST_STR="100 101"
445	echo -n $TEST_STR > $TARGET
446	# After we echo in, to help diff we need to set on TEST_STR what
447	# we expect the result to be.
448	TEST_STR="100 101 2 1"
449
450	if ! verify_diff_w "${TARGET}"; then
451		echo "FAIL" >&2
452		rc=1
453	else
454		echo "ok"
455	fi
456	test_rc
457
458	echo -n "Testing PAGE_SIZE limit on array works ... "
459	# Do not reset_vals, carry on the values from the last test.
460	# Even if you use an int array, you are still restricted to
461	# MAX_DIGITS, this is a known limitation. Test limit works.
462	LIMIT=$((MAX_DIGITS -1))
463	TEST_STR="9"
464	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
465		dd of="${TARGET}" 2>/dev/null
466
467	TEST_STR="9 101 2 1"
468	if ! verify_diff_w "${TARGET}"; then
469		echo "FAIL" >&2
470		rc=1
471	else
472		echo "ok"
473	fi
474	test_rc
475
476	echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "
477	# Do not reset_vals, carry on the values from the last test.
478	# Now go over limit.
479	LIMIT=$((MAX_DIGITS))
480	TEST_STR="7"
481	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
482		dd of="${TARGET}" 2>/dev/null
483
484	TEST_STR="7 101 2 1"
485	if verify_diff_w "${TARGET}"; then
486		echo "FAIL" >&2
487		rc=1
488	else
489		echo "ok"
490	fi
491	test_rc
492}
493
494# You are using an unsigned int
495run_limit_digit_uint()
496{
497	echo -n "Testing UINT_MAX works ..."
498	reset_vals
499	TEST_STR="$UINT_MAX"
500	echo -n $TEST_STR > $TARGET
501
502	if ! verify "${TARGET}"; then
503		echo "FAIL" >&2
504		rc=1
505	else
506		echo "ok"
507	fi
508	test_rc
509
510	echo -n "Testing UINT_MAX + 1 will fail as expected..."
511	reset_vals
512	TEST_STR=$(($UINT_MAX+1))
513	echo -n $TEST_STR > $TARGET 2> /dev/null
514
515	if verify "${TARGET}"; then
516		echo "FAIL" >&2
517		rc=1
518	else
519		echo "ok"
520	fi
521	test_rc
522
523	echo -n "Testing negative values will not work as expected ..."
524	reset_vals
525	TEST_STR="-3"
526	echo -n $TEST_STR > $TARGET 2> /dev/null
527
528	if verify "${TARGET}"; then
529		echo "FAIL" >&2
530		rc=1
531	else
532		echo "ok"
533	fi
534	test_rc
535}
536
537run_stringtests()
538{
539	echo -n "Writing entire sysctl in short writes ... "
540	set_orig
541	dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
542	if ! verify "${TARGET}"; then
543		echo "FAIL" >&2
544		rc=1
545	else
546		echo "ok"
547	fi
548
549	echo -n "Writing middle of sysctl after unsynchronized seek ... "
550	set_test
551	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
552	if verify "${TARGET}"; then
553		echo "FAIL" >&2
554		rc=1
555	else
556		echo "ok"
557	fi
558
559	echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
560	set_orig
561	perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
562		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
563	if ! grep -q B "${TARGET}"; then
564		echo "FAIL" >&2
565		rc=1
566	else
567		echo "ok"
568	fi
569
570	echo -n "Checking sysctl keeps original string on overflow append ... "
571	set_orig
572	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
573		dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
574	if grep -q B "${TARGET}"; then
575		echo "FAIL" >&2
576		rc=1
577	else
578		echo "ok"
579	fi
580
581	echo -n "Checking sysctl stays NULL terminated on write ... "
582	set_orig
583	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
584		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
585	if grep -q B "${TARGET}"; then
586		echo "FAIL" >&2
587		rc=1
588	else
589		echo "ok"
590	fi
591
592	echo -n "Checking sysctl stays NULL terminated on overwrite ... "
593	set_orig
594	perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
595		dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
596	if grep -q B "${TARGET}"; then
597		echo "FAIL" >&2
598		rc=1
599	else
600		echo "ok"
601	fi
602
603	test_rc
604}
605
606target_exists()
607{
608	TARGET="${SYSCTL}/$1"
609	TEST_ID="$2"
610
611	if [ ! -f ${TARGET} ] ; then
612		echo "Target for test $TEST_ID: $TARGET not exist, skipping test ..."
613		return 0
614	fi
615	return 1
616}
617
618sysctl_test_0001()
619{
620	TARGET="${SYSCTL}/$(get_test_target 0001)"
621	reset_vals
622	ORIG=$(cat "${TARGET}")
623	TEST_STR=$(( $ORIG + 1 ))
624
625	run_numerictests
626	run_wideint_tests
627	run_limit_digit
628}
629
630sysctl_test_0002()
631{
632	TARGET="${SYSCTL}/$(get_test_target 0002)"
633	reset_vals
634	ORIG=$(cat "${TARGET}")
635	TEST_STR="Testing sysctl"
636	# Only string sysctls support seeking/appending.
637	MAXLEN=65
638
639	run_numerictests
640	run_stringtests
641}
642
643sysctl_test_0003()
644{
645	TARGET="${SYSCTL}/$(get_test_target 0003)"
646	reset_vals
647	ORIG=$(cat "${TARGET}")
648	TEST_STR=$(( $ORIG + 1 ))
649
650	run_numerictests
651	run_wideint_tests
652	run_limit_digit
653	run_limit_digit_int
654}
655
656sysctl_test_0004()
657{
658	TARGET="${SYSCTL}/$(get_test_target 0004)"
659	reset_vals
660	ORIG=$(cat "${TARGET}")
661	TEST_STR=$(( $ORIG + 1 ))
662
663	run_numerictests
664	run_wideint_tests
665	run_limit_digit
666	run_limit_digit_uint
667}
668
669sysctl_test_0005()
670{
671	TARGET="${SYSCTL}/$(get_test_target 0005)"
672	reset_vals
673	ORIG=$(cat "${TARGET}")
674
675	run_limit_digit_int_array
676}
677
678list_tests()
679{
680	echo "Test ID list:"
681	echo
682	echo "TEST_ID x NUM_TEST"
683	echo "TEST_ID:   Test ID"
684	echo "NUM_TESTS: Number of recommended times to run the test"
685	echo
686	echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
687	echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
688	echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
689	echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
690	echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
691}
692
693usage()
694{
695	NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
696	let NUM_TESTS=$NUM_TESTS+1
697	MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
698	echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
699	echo "		 [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
700	echo "           [ all ] [ -h | --help ] [ -l ]"
701	echo ""
702	echo "Valid tests: 0001-$MAX_TEST"
703	echo ""
704	echo "    all     Runs all tests (default)"
705	echo "    -t      Run test ID the number amount of times is recommended"
706	echo "    -w      Watch test ID run until it runs into an error"
707	echo "    -c      Run test ID once"
708	echo "    -s      Run test ID x test-count number of times"
709	echo "    -l      List all test ID list"
710	echo " -h|--help  Help"
711	echo
712	echo "If an error every occurs execution will immediately terminate."
713	echo "If you are adding a new test try using -w <test-ID> first to"
714	echo "make sure the test passes a series of tests."
715	echo
716	echo Example uses:
717	echo
718	echo "$TEST_NAME.sh            -- executes all tests"
719	echo "$TEST_NAME.sh -t 0002    -- Executes test ID 0002 number of times is recomended"
720	echo "$TEST_NAME.sh -w 0002    -- Watch test ID 0002 run until an error occurs"
721	echo "$TEST_NAME.sh -s 0002    -- Run test ID 0002 once"
722	echo "$TEST_NAME.sh -c 0002 3  -- Run test ID 0002 three times"
723	echo
724	list_tests
725	exit 1
726}
727
728function test_num()
729{
730	re='^[0-9]+$'
731	if ! [[ $1 =~ $re ]]; then
732		usage
733	fi
734}
735
736function get_test_count()
737{
738	test_num $1
739	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
740	echo ${TEST_DATA} | awk -F":" '{print $2}'
741}
742
743function get_test_enabled()
744{
745	test_num $1
746	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
747	echo ${TEST_DATA} | awk -F":" '{print $3}'
748}
749
750function get_test_target()
751{
752	test_num $1
753	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
754	echo ${TEST_DATA} | awk -F":" '{print $4}'
755}
756
757function run_all_tests()
758{
759	for i in $ALL_TESTS ; do
760		TEST_ID=${i%:*:*:*}
761		ENABLED=$(get_test_enabled $TEST_ID)
762		TEST_COUNT=$(get_test_count $TEST_ID)
763		TEST_TARGET=$(get_test_target $TEST_ID)
764		target_exists $TEST_TARGET $TEST_ID
765		if [ $? -ne 1 ]; then
766			continue
767		fi
768		if [[ $ENABLED -eq "1" ]]; then
769			test_case $TEST_ID $TEST_COUNT $TEST_TARGET
770		fi
771	done
772}
773
774function watch_log()
775{
776	if [ $# -ne 3 ]; then
777		clear
778	fi
779	date
780	echo "Running test: $2 - run #$1"
781}
782
783function watch_case()
784{
785	i=0
786	while [ 1 ]; do
787
788		if [ $# -eq 1 ]; then
789			test_num $1
790			watch_log $i ${TEST_NAME}_test_$1
791			${TEST_NAME}_test_$1
792		else
793			watch_log $i all
794			run_all_tests
795		fi
796		let i=$i+1
797	done
798}
799
800function test_case()
801{
802	NUM_TESTS=$2
803
804	i=0
805
806	if target_exists $3 $1; then
807		continue
808	fi
809
810	while [ $i -lt $NUM_TESTS ]; do
811		test_num $1
812		watch_log $i ${TEST_NAME}_test_$1 noclear
813		RUN_TEST=${TEST_NAME}_test_$1
814		$RUN_TEST
815		let i=$i+1
816	done
817}
818
819function parse_args()
820{
821	if [ $# -eq 0 ]; then
822		run_all_tests
823	else
824		if [[ "$1" = "all" ]]; then
825			run_all_tests
826		elif [[ "$1" = "-w" ]]; then
827			shift
828			watch_case $@
829		elif [[ "$1" = "-t" ]]; then
830			shift
831			test_num $1
832			test_case $1 $(get_test_count $1) $(get_test_target $1)
833		elif [[ "$1" = "-c" ]]; then
834			shift
835			test_num $1
836			test_num $2
837			test_case $1 $2 $(get_test_target $1)
838		elif [[ "$1" = "-s" ]]; then
839			shift
840			test_case $1 1 $(get_test_target $1)
841		elif [[ "$1" = "-l" ]]; then
842			list_tests
843		elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
844			usage
845		else
846			usage
847		fi
848	fi
849}
850
851test_reqs
852allow_user_defaults
853check_production_sysctl_writes_strict
854load_req_mod
855test_modprobe
856
857trap "test_finish" EXIT
858
859parse_args $@
860
861exit 0
862