Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   1#!/bin/bash
   2# SPDX-License-Identifier: GPL-2.0-or-later OR copyleft-next-0.3.1
   3# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
   4
   5# This performs a series tests against the proc sysctl interface.
   6
   7# Kselftest framework requirement - SKIP code is 4.
   8ksft_skip=4
   9
  10TEST_NAME="sysctl"
  11TEST_DRIVER="test_${TEST_NAME}"
  12TEST_DIR=$(dirname $0)
  13TEST_FILE=$(mktemp)
  14
  15# This represents
  16#
  17# TEST_ID:TEST_COUNT:ENABLED:TARGET:SKIP_NO_TARGET
  18#
  19# TEST_ID: is the test id number
  20# TEST_COUNT: number of times we should run the test
  21# ENABLED: 1 if enabled, 0 otherwise
  22# TARGET: test target file required on the test_sysctl module
  23# SKIP_NO_TARGET: 1 skip if TARGET not there
  24#                 0 run eventhough TARGET not there
  25#
  26# Once these are enabled please leave them as-is. Write your own test,
  27# we have tons of space.
  28ALL_TESTS="0001:1:1:int_0001:1"
  29ALL_TESTS="$ALL_TESTS 0002:1:1:string_0001:1"
  30ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002:1"
  31ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001:1"
  32ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003:1"
  33ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001:1"
  34ALL_TESTS="$ALL_TESTS 0007:1:1:boot_int:1"
  35ALL_TESTS="$ALL_TESTS 0008:1:1:match_int:1"
  36ALL_TESTS="$ALL_TESTS 0009:1:1:unregister_error:0"
  37ALL_TESTS="$ALL_TESTS 0010:1:1:mnt/mnt_error:0"
  38ALL_TESTS="$ALL_TESTS 0011:1:1:empty_add:0"
  39
  40function allow_user_defaults()
  41{
  42	if [ -z $DIR ]; then
  43		DIR="/sys/module/test_sysctl/"
  44	fi
  45	if [ -z $DEFAULT_NUM_TESTS ]; then
  46		DEFAULT_NUM_TESTS=50
  47	fi
  48	if [ -z $SYSCTL ]; then
  49		SYSCTL="/proc/sys/debug/test_sysctl"
  50	fi
  51	if [ -z $PROD_SYSCTL ]; then
  52		PROD_SYSCTL="/proc/sys"
  53	fi
  54	if [ -z $WRITES_STRICT ]; then
  55		WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"
  56	fi
  57}
  58
  59function check_production_sysctl_writes_strict()
  60{
  61	echo -n "Checking production write strict setting ... "
  62	if [ ! -e ${WRITES_STRICT} ]; then
  63		echo "FAIL, but skip in case of old kernel" >&2
  64	else
  65		old_strict=$(cat ${WRITES_STRICT})
  66		if [ "$old_strict" = "1" ]; then
  67			echo "OK"
  68		else
  69			echo "FAIL, strict value is 0 but force to 1 to continue" >&2
  70			echo "1" > ${WRITES_STRICT}
  71		fi
  72	fi
  73
  74	if [ -z $PAGE_SIZE ]; then
  75		PAGE_SIZE=$(getconf PAGESIZE)
  76	fi
  77	if [ -z $MAX_DIGITS ]; then
  78		MAX_DIGITS=$(($PAGE_SIZE/8))
  79	fi
  80	if [ -z $INT_MAX ]; then
  81		INT_MAX=$(getconf INT_MAX)
  82	fi
  83	if [ -z $UINT_MAX ]; then
  84		UINT_MAX=$(getconf UINT_MAX)
  85	fi
  86}
  87
  88test_reqs()
  89{
  90	uid=$(id -u)
  91	if [ $uid -ne 0 ]; then
  92		echo $msg must be run as root >&2
  93		exit $ksft_skip
  94	fi
  95
  96	if ! which perl 2> /dev/null > /dev/null; then
  97		echo "$0: You need perl installed"
  98		exit $ksft_skip
  99	fi
 100	if ! which getconf 2> /dev/null > /dev/null; then
 101		echo "$0: You need getconf installed"
 102		exit $ksft_skip
 103	fi
 104	if ! which diff 2> /dev/null > /dev/null; then
 105		echo "$0: You need diff installed"
 106		exit $ksft_skip
 107	fi
 108}
 109
 110function load_req_mod()
 111{
 112	if [ ! -d $SYSCTL ]; then
 113		if ! modprobe -q -n $TEST_DRIVER; then
 114			echo "$0: module $TEST_DRIVER not found [SKIP]"
 115			echo "You must set CONFIG_TEST_SYSCTL=m in your kernel" >&2
 116			exit $ksft_skip
 117		fi
 118		modprobe $TEST_DRIVER
 119		if [ $? -ne 0 ]; then
 120			echo "$0: modprobe $TEST_DRIVER failed."
 121			exit
 122		fi
 123	fi
 124}
 125
 126reset_vals()
 127{
 128	VAL=""
 129	TRIGGER=$(basename ${TARGET})
 130	case "$TRIGGER" in
 131		int_0001)
 132			VAL="60"
 133			;;
 134		int_0002)
 135			VAL="1"
 136			;;
 137		uint_0001)
 138			VAL="314"
 139			;;
 140		string_0001)
 141			VAL="(none)"
 142			;;
 143		bitmap_0001)
 144			VAL=""
 145			;;
 146		*)
 147			;;
 148	esac
 149	echo -n $VAL > $TARGET
 150}
 151
 152set_orig()
 153{
 154	if [ ! -z $TARGET ] && [ ! -z $ORIG ]; then
 155		if [ -f ${TARGET} ]; then
 156			echo "${ORIG}" > "${TARGET}"
 157		fi
 158	fi
 159}
 160
 161set_test()
 162{
 163	echo "${TEST_STR}" > "${TARGET}"
 164}
 165
 166verify()
 167{
 168	local seen
 169	seen=$(cat "$1")
 170	if [ "${seen}" != "${TEST_STR}" ]; then
 171		return 1
 172	fi
 173	return 0
 174}
 175
 176# proc files get read a page at a time, which can confuse diff,
 177# and get you incorrect results on proc files with long data. To use
 178# diff against them you must first extract the output to a file, and
 179# then compare against that file.
 180verify_diff_proc_file()
 181{
 182	TMP_DUMP_FILE=$(mktemp)
 183	cat $1 > $TMP_DUMP_FILE
 184
 185	if ! diff -w -q $TMP_DUMP_FILE $2; then
 186		return 1
 187	else
 188		return 0
 189	fi
 190}
 191
 192verify_diff_w()
 193{
 194	echo "$TEST_STR" | diff -q -w -u - $1 > /dev/null
 195	return $?
 196}
 197
 198test_rc()
 199{
 200	if [[ $rc != 0 ]]; then
 201		echo "Failed test, return value: $rc" >&2
 202		exit $rc
 203	fi
 204}
 205
 206test_finish()
 207{
 208	set_orig
 209	rm -f "${TEST_FILE}"
 210
 211	if [ ! -z ${old_strict} ]; then
 212		echo ${old_strict} > ${WRITES_STRICT}
 213	fi
 214	exit $rc
 215}
 216
 217run_numerictests()
 218{
 219	echo "== Testing sysctl behavior against ${TARGET} =="
 220
 221	rc=0
 222
 223	echo -n "Writing test file ... "
 224	echo "${TEST_STR}" > "${TEST_FILE}"
 225	if ! verify "${TEST_FILE}"; then
 226		echo "FAIL" >&2
 227		exit 1
 228	else
 229		echo "OK"
 230	fi
 231
 232	echo -n "Checking sysctl is not set to test value ... "
 233	if verify "${TARGET}"; then
 234		echo "FAIL" >&2
 235		exit 1
 236	else
 237		echo "OK"
 238	fi
 239
 240	echo -n "Writing sysctl from shell ... "
 241	set_test
 242	if ! verify "${TARGET}"; then
 243		echo "FAIL" >&2
 244		exit 1
 245	else
 246		echo "OK"
 247	fi
 248
 249	echo -n "Resetting sysctl to original value ... "
 250	set_orig
 251	if verify "${TARGET}"; then
 252		echo "FAIL" >&2
 253		exit 1
 254	else
 255		echo "OK"
 256	fi
 257
 258	# Now that we've validated the sanity of "set_test" and "set_orig",
 259	# we can use those functions to set starting states before running
 260	# specific behavioral tests.
 261
 262	echo -n "Writing entire sysctl in single write ... "
 263	set_orig
 264	dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
 265	if ! verify "${TARGET}"; then
 266		echo "FAIL" >&2
 267		rc=1
 268	else
 269		echo "OK"
 270	fi
 271
 272	echo -n "Writing middle of sysctl after synchronized seek ... "
 273	set_test
 274	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
 275	if ! verify "${TARGET}"; then
 276		echo "FAIL" >&2
 277		rc=1
 278	else
 279		echo "OK"
 280	fi
 281
 282	echo -n "Writing beyond end of sysctl ... "
 283	set_orig
 284	dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
 285	if verify "${TARGET}"; then
 286		echo "FAIL" >&2
 287		rc=1
 288	else
 289		echo "OK"
 290	fi
 291
 292	echo -n "Writing sysctl with multiple long writes ... "
 293	set_orig
 294	(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
 295		dd of="${TARGET}" bs=50 2>/dev/null
 296	if verify "${TARGET}"; then
 297		echo "FAIL" >&2
 298		rc=1
 299	else
 300		echo "OK"
 301	fi
 302	test_rc
 303}
 304
 305check_failure()
 306{
 307	echo -n "Testing that $1 fails as expected ... "
 308	reset_vals
 309	TEST_STR="$1"
 310	orig="$(cat $TARGET)"
 311	echo -n "$TEST_STR" > $TARGET 2> /dev/null
 312
 313	# write should fail and $TARGET should retain its original value
 314	if [ $? = 0 ] || [ "$(cat $TARGET)" != "$orig" ]; then
 315		echo "FAIL" >&2
 316		rc=1
 317	else
 318		echo "OK"
 319	fi
 320	test_rc
 321}
 322
 323run_wideint_tests()
 324{
 325	# sysctl conversion functions receive a boolean sign and ulong
 326	# magnitude; here we list the magnitudes we want to test (each of
 327	# which will be tested in both positive and negative forms).  Since
 328	# none of these values fit in 32 bits, writing them to an int- or
 329	# uint-typed sysctl should fail.
 330	local magnitudes=(
 331		# common boundary-condition values (zero, +1, -1, INT_MIN,
 332		# and INT_MAX respectively) if truncated to lower 32 bits
 333		# (potential for being falsely deemed in range)
 334		0x0000000100000000
 335		0x0000000100000001
 336		0x00000001ffffffff
 337		0x0000000180000000
 338		0x000000017fffffff
 339
 340		# these look like negatives, but without a leading '-' are
 341		# actually large positives (should be rejected as above
 342		# despite being zero/+1/-1/INT_MIN/INT_MAX in the lower 32)
 343		0xffffffff00000000
 344		0xffffffff00000001
 345		0xffffffffffffffff
 346		0xffffffff80000000
 347		0xffffffff7fffffff
 348	)
 349
 350	for sign in '' '-'; do
 351		for mag in "${magnitudes[@]}"; do
 352			check_failure "${sign}${mag}"
 353		done
 354	done
 355}
 356
 357# Your test must accept digits 3 and 4 to use this
 358run_limit_digit()
 359{
 360	echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ... "
 361	reset_vals
 362
 363	LIMIT=$((MAX_DIGITS -1))
 364	TEST_STR="3"
 365	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
 366		dd of="${TARGET}" 2>/dev/null
 367
 368	if ! verify "${TARGET}"; then
 369		echo "FAIL" >&2
 370		rc=1
 371	else
 372		echo "OK"
 373	fi
 374	test_rc
 375
 376	echo -n "Checking passing PAGE_SIZE of spaces fails on write ... "
 377	reset_vals
 378
 379	LIMIT=$((MAX_DIGITS))
 380	TEST_STR="4"
 381	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
 382		dd of="${TARGET}" 2>/dev/null
 383
 384	if verify "${TARGET}"; then
 385		echo "FAIL" >&2
 386		rc=1
 387	else
 388		echo "OK"
 389	fi
 390	test_rc
 391}
 392
 393# You are using an int
 394run_limit_digit_int()
 395{
 396	echo -n "Testing INT_MAX works ... "
 397	reset_vals
 398	TEST_STR="$INT_MAX"
 399	echo -n $TEST_STR > $TARGET
 400
 401	if ! verify "${TARGET}"; then
 402		echo "FAIL" >&2
 403		rc=1
 404	else
 405		echo "OK"
 406	fi
 407	test_rc
 408
 409	echo -n "Testing INT_MAX + 1 will fail as expected ... "
 410	reset_vals
 411	let TEST_STR=$INT_MAX+1
 412	echo -n $TEST_STR > $TARGET 2> /dev/null
 413
 414	if verify "${TARGET}"; then
 415		echo "FAIL" >&2
 416		rc=1
 417	else
 418		echo "OK"
 419	fi
 420	test_rc
 421
 422	echo -n "Testing negative values will work as expected ... "
 423	reset_vals
 424	TEST_STR="-3"
 425	echo -n $TEST_STR > $TARGET 2> /dev/null
 426	if ! verify "${TARGET}"; then
 427		echo "FAIL" >&2
 428		rc=1
 429	else
 430		echo "OK"
 431	fi
 432	test_rc
 433}
 434
 435# You used an int array
 436run_limit_digit_int_array()
 437{
 438	echo -n "Testing array works as expected ... "
 439	TEST_STR="4 3 2 1"
 440	echo -n $TEST_STR > $TARGET
 441
 442	if ! verify_diff_w "${TARGET}"; then
 443		echo "FAIL" >&2
 444		rc=1
 445	else
 446		echo "OK"
 447	fi
 448	test_rc
 449
 450	echo -n "Testing skipping trailing array elements works ... "
 451	# Do not reset_vals, carry on the values from the last test.
 452	# If we only echo in two digits the last two are left intact
 453	TEST_STR="100 101"
 454	echo -n $TEST_STR > $TARGET
 455	# After we echo in, to help diff we need to set on TEST_STR what
 456	# we expect the result to be.
 457	TEST_STR="100 101 2 1"
 458
 459	if ! verify_diff_w "${TARGET}"; then
 460		echo "FAIL" >&2
 461		rc=1
 462	else
 463		echo "OK"
 464	fi
 465	test_rc
 466
 467	echo -n "Testing PAGE_SIZE limit on array works ... "
 468	# Do not reset_vals, carry on the values from the last test.
 469	# Even if you use an int array, you are still restricted to
 470	# MAX_DIGITS, this is a known limitation. Test limit works.
 471	LIMIT=$((MAX_DIGITS -1))
 472	TEST_STR="9"
 473	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
 474		dd of="${TARGET}" 2>/dev/null
 475
 476	TEST_STR="9 101 2 1"
 477	if ! verify_diff_w "${TARGET}"; then
 478		echo "FAIL" >&2
 479		rc=1
 480	else
 481		echo "OK"
 482	fi
 483	test_rc
 484
 485	echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "
 486	# Do not reset_vals, carry on the values from the last test.
 487	# Now go over limit.
 488	LIMIT=$((MAX_DIGITS))
 489	TEST_STR="7"
 490	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
 491		dd of="${TARGET}" 2>/dev/null
 492
 493	TEST_STR="7 101 2 1"
 494	if verify_diff_w "${TARGET}"; then
 495		echo "FAIL" >&2
 496		rc=1
 497	else
 498		echo "OK"
 499	fi
 500	test_rc
 501}
 502
 503# You are using an unsigned int
 504run_limit_digit_uint()
 505{
 506	echo -n "Testing UINT_MAX works ... "
 507	reset_vals
 508	TEST_STR="$UINT_MAX"
 509	echo -n $TEST_STR > $TARGET
 510
 511	if ! verify "${TARGET}"; then
 512		echo "FAIL" >&2
 513		rc=1
 514	else
 515		echo "OK"
 516	fi
 517	test_rc
 518
 519	echo -n "Testing UINT_MAX + 1 will fail as expected ... "
 520	reset_vals
 521	TEST_STR=$(($UINT_MAX+1))
 522	echo -n $TEST_STR > $TARGET 2> /dev/null
 523
 524	if verify "${TARGET}"; then
 525		echo "FAIL" >&2
 526		rc=1
 527	else
 528		echo "OK"
 529	fi
 530	test_rc
 531
 532	echo -n "Testing negative values will not work as expected ... "
 533	reset_vals
 534	TEST_STR="-3"
 535	echo -n $TEST_STR > $TARGET 2> /dev/null
 536
 537	if verify "${TARGET}"; then
 538		echo "FAIL" >&2
 539		rc=1
 540	else
 541		echo "OK"
 542	fi
 543	test_rc
 544}
 545
 546run_stringtests()
 547{
 548	echo -n "Writing entire sysctl in short writes ... "
 549	set_orig
 550	dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
 551	if ! verify "${TARGET}"; then
 552		echo "FAIL" >&2
 553		rc=1
 554	else
 555		echo "OK"
 556	fi
 557
 558	echo -n "Writing middle of sysctl after unsynchronized seek ... "
 559	set_test
 560	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
 561	if verify "${TARGET}"; then
 562		echo "FAIL" >&2
 563		rc=1
 564	else
 565		echo "OK"
 566	fi
 567
 568	echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
 569	set_orig
 570	perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
 571		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
 572	if ! grep -q B "${TARGET}"; then
 573		echo "FAIL" >&2
 574		rc=1
 575	else
 576		echo "OK"
 577	fi
 578
 579	echo -n "Checking sysctl keeps original string on overflow append ... "
 580	set_orig
 581	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
 582		dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
 583	if grep -q B "${TARGET}"; then
 584		echo "FAIL" >&2
 585		rc=1
 586	else
 587		echo "OK"
 588	fi
 589
 590	echo -n "Checking sysctl stays NULL terminated on write ... "
 591	set_orig
 592	perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
 593		dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
 594	if grep -q B "${TARGET}"; then
 595		echo "FAIL" >&2
 596		rc=1
 597	else
 598		echo "OK"
 599	fi
 600
 601	echo -n "Checking sysctl stays NULL terminated on overwrite ... "
 602	set_orig
 603	perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
 604		dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
 605	if grep -q B "${TARGET}"; then
 606		echo "FAIL" >&2
 607		rc=1
 608	else
 609		echo "OK"
 610	fi
 611
 612	test_rc
 613}
 614
 615target_exists()
 616{
 617	TARGET="${SYSCTL}/$1"
 618	TEST_ID="$2"
 619
 620	if [ ! -f ${TARGET} ] ; then
 621		return 0
 622	fi
 623	return 1
 624}
 625
 626run_bitmaptest() {
 627	# Total length of bitmaps string to use, a bit under
 628	# the maximum input size of the test node
 629	LENGTH=$((RANDOM % 65000))
 630
 631	# First bit to set
 632	BIT=$((RANDOM % 1024))
 633
 634	# String containing our list of bits to set
 635	TEST_STR=$BIT
 636
 637	# build up the string
 638	while [ "${#TEST_STR}" -le "$LENGTH" ]; do
 639		# Make sure next entry is discontiguous,
 640		# skip ahead at least 2
 641		BIT=$((BIT + $((2 + RANDOM % 10))))
 642
 643		# Add new bit to the list
 644		TEST_STR="${TEST_STR},${BIT}"
 645
 646		# Randomly make it a range
 647		if [ "$((RANDOM % 2))" -eq "1" ]; then
 648			RANGE_END=$((BIT + $((1 + RANDOM % 10))))
 649			TEST_STR="${TEST_STR}-${RANGE_END}"
 650			BIT=$RANGE_END
 651		fi
 652	done
 653
 654	echo -n "Checking bitmap handler ... "
 655	TEST_FILE=$(mktemp)
 656	echo -n "$TEST_STR" > $TEST_FILE
 657
 658	cat $TEST_FILE > $TARGET 2> /dev/null
 659	if [ $? -ne 0 ]; then
 660		echo "FAIL" >&2
 661		rc=1
 662		test_rc
 663	fi
 664
 665	if ! verify_diff_proc_file "$TARGET" "$TEST_FILE"; then
 666		echo "FAIL" >&2
 667		rc=1
 668	else
 669		echo "OK"
 670		rc=0
 671	fi
 672	test_rc
 673}
 674
 675sysctl_test_0001()
 676{
 677	TARGET="${SYSCTL}/$(get_test_target 0001)"
 678	reset_vals
 679	ORIG=$(cat "${TARGET}")
 680	TEST_STR=$(( $ORIG + 1 ))
 681
 682	run_numerictests
 683	run_wideint_tests
 684	run_limit_digit
 685}
 686
 687sysctl_test_0002()
 688{
 689	TARGET="${SYSCTL}/$(get_test_target 0002)"
 690	reset_vals
 691	ORIG=$(cat "${TARGET}")
 692	TEST_STR="Testing sysctl"
 693	# Only string sysctls support seeking/appending.
 694	MAXLEN=65
 695
 696	run_numerictests
 697	run_stringtests
 698}
 699
 700sysctl_test_0003()
 701{
 702	TARGET="${SYSCTL}/$(get_test_target 0003)"
 703	reset_vals
 704	ORIG=$(cat "${TARGET}")
 705	TEST_STR=$(( $ORIG + 1 ))
 706
 707	run_numerictests
 708	run_wideint_tests
 709	run_limit_digit
 710	run_limit_digit_int
 711}
 712
 713sysctl_test_0004()
 714{
 715	TARGET="${SYSCTL}/$(get_test_target 0004)"
 716	reset_vals
 717	ORIG=$(cat "${TARGET}")
 718	TEST_STR=$(( $ORIG + 1 ))
 719
 720	run_numerictests
 721	run_wideint_tests
 722	run_limit_digit
 723	run_limit_digit_uint
 724}
 725
 726sysctl_test_0005()
 727{
 728	TARGET="${SYSCTL}/$(get_test_target 0005)"
 729	reset_vals
 730	ORIG=$(cat "${TARGET}")
 731
 732	run_limit_digit_int_array
 733}
 734
 735sysctl_test_0006()
 736{
 737	TARGET="${SYSCTL}/$(get_test_target 0006)"
 738	reset_vals
 739	ORIG=""
 740	run_bitmaptest
 741}
 742
 743sysctl_test_0007()
 744{
 745	TARGET="${SYSCTL}/$(get_test_target 0007)"
 746	echo -n "Testing if $TARGET is set to 1 ... "
 747
 748	if [ ! -f $TARGET ]; then
 749		echo -e "SKIPPING\n$TARGET is not present"
 750		return $ksft_skip
 751	fi
 752
 753	if [ -d $DIR ]; then
 754		echo -e "SKIPPING\nTest only possible if sysctl_test is built-in, not module:"
 755		cat $TEST_DIR/config >&2
 756		return $ksft_skip
 757	fi
 758
 759	ORIG=$(cat "${TARGET}")
 760
 761	if [ x$ORIG = "x1" ]; then
 762		echo "OK"
 763		return 0
 764	fi
 765
 766	if [ ! -f /proc/cmdline ]; then
 767		echo -e "SKIPPING\nThere is no /proc/cmdline to check for paramter"
 768		return $ksft_skip
 769	fi
 770
 771	FOUND=$(grep -c "sysctl[./]debug[./]test_sysctl[./]boot_int=1" /proc/cmdline)
 772	if [ $FOUND = "1" ]; then
 773		echo -e "FAIL\nKernel param found but $TARGET is not 1." >&2
 774		rc=1
 775		test_rc
 776	fi
 777
 778	echo -e "SKIPPING\nExpected kernel parameter missing."
 779	echo "Kernel must be booted with parameter: sysctl.debug.test_sysctl.boot_int=1"
 780	return $ksft_skip
 781}
 782
 783sysctl_test_0008()
 784{
 785	TARGET="${SYSCTL}/$(get_test_target 0008)"
 786	echo -n "Testing if $TARGET is matched in kernel ... "
 787
 788	if [ ! -f $TARGET ]; then
 789		echo -e "SKIPPING\n$TARGET is not present"
 790		return $ksft_skip
 791	fi
 792
 793	ORIG_VALUE=$(cat "${TARGET}")
 794
 795	if [ $ORIG_VALUE -ne 1 ]; then
 796		echo "FAIL" >&2
 797		rc=1
 798		test_rc
 799	fi
 800
 801	echo "OK"
 802	return 0
 803}
 804
 805sysctl_test_0009()
 806{
 807	TARGET="${SYSCTL}/$(get_test_target 0009)"
 808	echo -n "Testing if $TARGET unregistered correctly ... "
 809	if [ -d $TARGET ]; then
 810		echo "FAIL" >&2
 811		rc=1
 812		test_rc
 813	fi
 814
 815	echo "OK"
 816	return 0
 817}
 818
 819sysctl_test_0010()
 820{
 821	TARGET="${SYSCTL}/$(get_test_target 0010)"
 822	echo -n "Testing that $TARGET was not created ... "
 823	if [ -d $TARGET ]; then
 824		echo "FAIL" >&2
 825		rc=1
 826		test_rc
 827	fi
 828
 829	echo "OK"
 830	return 0
 831}
 832
 833sysctl_test_0011()
 834{
 835	TARGET="${SYSCTL}/$(get_test_target 0011)"
 836	echo -n "Testing empty dir handling in ${TARGET} ... "
 837	if [ ! -d ${TARGET} ]; then
 838		echo -e "FAIL\nCould not create ${TARGET}" >&2
 839		rc=1
 840		test_rc
 841	fi
 842
 843	TARGET2="${TARGET}/empty"
 844	if [ ! -d ${TARGET2} ]; then
 845		echo -e "FAIL\nCould not create ${TARGET2}" >&2
 846		rc=1
 847		test_rc
 848	fi
 849
 850	echo "OK"
 851	return 0
 852}
 853
 854list_tests()
 855{
 856	echo "Test ID list:"
 857	echo
 858	echo "TEST_ID x NUM_TEST"
 859	echo "TEST_ID:   Test ID"
 860	echo "NUM_TESTS: Number of recommended times to run the test"
 861	echo
 862	echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
 863	echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
 864	echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
 865	echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
 866	echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
 867	echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()"
 868	echo "0007 x $(get_test_count 0007) - tests setting sysctl from kernel boot param"
 869	echo "0008 x $(get_test_count 0008) - tests sysctl macro values match"
 870	echo "0009 x $(get_test_count 0009) - tests sysct unregister"
 871	echo "0010 x $(get_test_count 0010) - tests sysct mount point"
 872	echo "0011 x $(get_test_count 0011) - tests empty directories"
 873}
 874
 875usage()
 876{
 877	NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
 878	let NUM_TESTS=$NUM_TESTS+1
 879	MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
 880	echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
 881	echo "		 [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
 882	echo "           [ all ] [ -h | --help ] [ -l ]"
 883	echo ""
 884	echo "Valid tests: 0001-$MAX_TEST"
 885	echo ""
 886	echo "    all     Runs all tests (default)"
 887	echo "    -t      Run test ID the number amount of times is recommended"
 888	echo "    -w      Watch test ID run until it runs into an error"
 889	echo "    -c      Run test ID once"
 890	echo "    -s      Run test ID x test-count number of times"
 891	echo "    -l      List all test ID list"
 892	echo " -h|--help  Help"
 893	echo
 894	echo "If an error every occurs execution will immediately terminate."
 895	echo "If you are adding a new test try using -w <test-ID> first to"
 896	echo "make sure the test passes a series of tests."
 897	echo
 898	echo Example uses:
 899	echo
 900	echo "$TEST_NAME.sh            -- executes all tests"
 901	echo "$TEST_NAME.sh -t 0002    -- Executes test ID 0002 number of times is recomended"
 902	echo "$TEST_NAME.sh -w 0002    -- Watch test ID 0002 run until an error occurs"
 903	echo "$TEST_NAME.sh -s 0002    -- Run test ID 0002 once"
 904	echo "$TEST_NAME.sh -c 0002 3  -- Run test ID 0002 three times"
 905	echo
 906	list_tests
 907	exit 1
 908}
 909
 910function test_num()
 911{
 912	re='^[0-9]+$'
 913	if ! [[ $1 =~ $re ]]; then
 914		usage
 915	fi
 916}
 917function remove_leading_zeros()
 918{
 919	echo $1 | sed 's/^0*//'
 920}
 921
 922function get_test_count()
 923{
 924	test_num $1
 925	awk_field=$(remove_leading_zeros $1)
 926	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$awk_field'}')
 927	echo ${TEST_DATA} | awk -F":" '{print $2}'
 928}
 929
 930function get_test_enabled()
 931{
 932	test_num $1
 933	awk_field=$(remove_leading_zeros $1)
 934	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$awk_field'}')
 935	echo ${TEST_DATA} | awk -F":" '{print $3}'
 936}
 937
 938function get_test_target()
 939{
 940	test_num $1
 941	awk_field=$(remove_leading_zeros $1)
 942	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$awk_field'}')
 943	echo ${TEST_DATA} | awk -F":" '{print $4}'
 944}
 945
 946function get_test_skip_no_target()
 947{
 948	test_num $1
 949	awk_field=$(remove_leading_zeros $1)
 950	TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$awk_field'}')
 951	echo ${TEST_DATA} | awk -F":" '{print $5}'
 952}
 953
 954function skip_test()
 955{
 956	TEST_ID=$1
 957	TEST_TARGET=$2
 958	if target_exists $TEST_TARGET $TEST_ID; then
 959		TEST_SKIP=$(get_test_skip_no_target $TEST_ID)
 960		if [[ $TEST_SKIP -eq "1" ]]; then
 961			echo "Target $TEST_TARGET for test $TEST_ID does not exist ... SKIPPING"
 962			return 0
 963		fi
 964	fi
 965	return 1
 966}
 967
 968function run_all_tests()
 969{
 970	for i in $ALL_TESTS ; do
 971		TEST_ID=${i%:*:*:*:*}
 972		ENABLED=$(get_test_enabled $TEST_ID)
 973		TEST_COUNT=$(get_test_count $TEST_ID)
 974		TEST_TARGET=$(get_test_target $TEST_ID)
 975
 976		if [[ $ENABLED -eq "1" ]]; then
 977			test_case $TEST_ID $TEST_COUNT $TEST_TARGET
 978		fi
 979	done
 980}
 981
 982function watch_log()
 983{
 984	if [ $# -ne 3 ]; then
 985		clear
 986	fi
 987	date
 988	echo "Running test: $2 - run #$1"
 989}
 990
 991function watch_case()
 992{
 993	i=0
 994	while [ 1 ]; do
 995
 996		if [ $# -eq 1 ]; then
 997			test_num $1
 998			watch_log $i ${TEST_NAME}_test_$1
 999			${TEST_NAME}_test_$1
1000		else
1001			watch_log $i all
1002			run_all_tests
1003		fi
1004		let i=$i+1
1005	done
1006}
1007
1008function test_case()
1009{
1010	TEST_ID=$1
1011	NUM_TESTS=$2
1012	TARGET=$3
1013
1014	if skip_test $TEST_ID $TARGET; then
1015		return
1016	fi
1017
1018	i=0
1019	while [ $i -lt $NUM_TESTS ]; do
1020		test_num $TEST_ID
1021		watch_log $i ${TEST_NAME}_test_${TEST_ID} noclear
1022		RUN_TEST=${TEST_NAME}_test_${TEST_ID}
1023		$RUN_TEST
1024		let i=$i+1
1025	done
1026}
1027
1028function parse_args()
1029{
1030	if [ $# -eq 0 ]; then
1031		run_all_tests
1032	else
1033		if [[ "$1" = "all" ]]; then
1034			run_all_tests
1035		elif [[ "$1" = "-w" ]]; then
1036			shift
1037			watch_case $@
1038		elif [[ "$1" = "-t" ]]; then
1039			shift
1040			test_num $1
1041			test_case $1 $(get_test_count $1) $(get_test_target $1)
1042		elif [[ "$1" = "-c" ]]; then
1043			shift
1044			test_num $1
1045			test_num $2
1046			test_case $1 $2 $(get_test_target $1)
1047		elif [[ "$1" = "-s" ]]; then
1048			shift
1049			test_case $1 1 $(get_test_target $1)
1050		elif [[ "$1" = "-l" ]]; then
1051			list_tests
1052		elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
1053			usage
1054		else
1055			usage
1056		fi
1057	fi
1058}
1059
1060test_reqs
1061allow_user_defaults
1062check_production_sysctl_writes_strict
1063load_req_mod
1064
1065trap "test_finish" EXIT
1066
1067parse_args $@
1068
1069exit 0