774 lines · 14.8 KB · Shell
RawDownload
#!/bin/bash# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>## This program is free software; you can redistribute it and/or modify it# under the terms of the GNU General Public License as published by the Free# Software Foundation; either version 2 of the License, or at your option any# later version; or, when distributed separately from the Linux kernel or# when incorporated into other software packages, subject to the following# license:## This program is free software; you can redistribute it and/or modify it# under the terms of copyleft-next (version 0.3.1 or later) as published# at http://copyleft-next.org/. # This performs a series tests against the proc sysctl interface. TEST_NAME="sysctl"TEST_DRIVER="test_${TEST_NAME}"TEST_DIR=$(dirname $0)TEST_FILE=$(mktemp) # This represents## TEST_ID:TEST_COUNT:ENABLED## TEST_ID: is the test id number# TEST_COUNT: number of times we should run the test# ENABLED: 1 if enabled, 0 otherwise## Once these are enabled please leave them as-is. Write your own test,# we have tons of space.ALL_TESTS="0001:1:1"ALL_TESTS="$ALL_TESTS 0002:1:1"ALL_TESTS="$ALL_TESTS 0003:1:1"ALL_TESTS="$ALL_TESTS 0004:1:1"ALL_TESTS="$ALL_TESTS 0005:3:1" test_modprobe(){       if [ ! -d $DIR ]; then               echo "$0: $DIR not present" >&2               echo "You must have the following enabled in your kernel:" >&2               cat $TEST_DIR/config >&2               exit 1       fi} function allow_user_defaults(){	if [ -z $DIR ]; then		DIR="/sys/module/test_sysctl/"	fi	if [ -z $DEFAULT_NUM_TESTS ]; then		DEFAULT_NUM_TESTS=50	fi	if [ -z $SYSCTL ]; then		SYSCTL="/proc/sys/debug/test_sysctl"	fi	if [ -z $PROD_SYSCTL ]; then		PROD_SYSCTL="/proc/sys"	fi	if [ -z $WRITES_STRICT ]; then		WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"	fi} function check_production_sysctl_writes_strict(){	echo -n "Checking production write strict setting ... "	if [ ! -e ${WRITES_STRICT} ]; then		echo "FAIL, but skip in case of old kernel" >&2	else		old_strict=$(cat ${WRITES_STRICT})		if [ "$old_strict" = "1" ]; then			echo "ok"		else			echo "FAIL, strict value is 0 but force to 1 to continue" >&2			echo "1" > ${WRITES_STRICT}		fi	fi 	if [ -z $PAGE_SIZE ]; then		PAGE_SIZE=$(getconf PAGESIZE)	fi	if [ -z $MAX_DIGITS ]; then		MAX_DIGITS=$(($PAGE_SIZE/8))	fi	if [ -z $INT_MAX ]; then		INT_MAX=$(getconf INT_MAX)	fi	if [ -z $UINT_MAX ]; then		UINT_MAX=$(getconf UINT_MAX)	fi} test_reqs(){	uid=$(id -u)	if [ $uid -ne 0 ]; then		echo $msg must be run as root >&2		exit 0	fi 	if ! which perl 2> /dev/null > /dev/null; then		echo "$0: You need perl installed"		exit 1	fi	if ! which getconf 2> /dev/null > /dev/null; then		echo "$0: You need getconf installed"		exit 1	fi	if ! which diff 2> /dev/null > /dev/null; then		echo "$0: You need diff installed"		exit 1	fi} function load_req_mod(){	trap "test_modprobe" EXIT 	if [ ! -d $DIR ]; then		modprobe $TEST_DRIVER		if [ $? -ne 0 ]; then			exit		fi	fi} reset_vals(){	VAL=""	TRIGGER=$(basename ${TARGET})	case "$TRIGGER" in		int_0001)			VAL="60"			;;		int_0002)			VAL="1"			;;		uint_0001)			VAL="314"			;;		string_0001)			VAL="(none)"			;;		*)			;;	esac	echo -n $VAL > $TARGET} set_orig(){	if [ ! -z $TARGET ]; then		echo "${ORIG}" > "${TARGET}"	fi} set_test(){	echo "${TEST_STR}" > "${TARGET}"} verify(){	local seen	seen=$(cat "$1")	if [ "${seen}" != "${TEST_STR}" ]; then		return 1	fi	return 0} verify_diff_w(){	echo "$TEST_STR" | diff -q -w -u - $1	return $?} test_rc(){	if [[ $rc != 0 ]]; then		echo "Failed test, return value: $rc" >&2		exit $rc	fi} test_finish(){	set_orig	rm -f "${TEST_FILE}" 	if [ ! -z ${old_strict} ]; then		echo ${old_strict} > ${WRITES_STRICT}	fi	exit $rc} run_numerictests(){	echo "== Testing sysctl behavior against ${TARGET} ==" 	rc=0 	echo -n "Writing test file ... "	echo "${TEST_STR}" > "${TEST_FILE}"	if ! verify "${TEST_FILE}"; then		echo "FAIL" >&2		exit 1	else		echo "ok"	fi 	echo -n "Checking sysctl is not set to test value ... "	if verify "${TARGET}"; then		echo "FAIL" >&2		exit 1	else		echo "ok"	fi 	echo -n "Writing sysctl from shell ... "	set_test	if ! verify "${TARGET}"; then		echo "FAIL" >&2		exit 1	else		echo "ok"	fi 	echo -n "Resetting sysctl to original value ... "	set_orig	if verify "${TARGET}"; then		echo "FAIL" >&2		exit 1	else		echo "ok"	fi 	# Now that we've validated the sanity of "set_test" and "set_orig",	# we can use those functions to set starting states before running	# specific behavioral tests. 	echo -n "Writing entire sysctl in single write ... "	set_orig	dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi 	echo -n "Writing middle of sysctl after synchronized seek ... "	set_test	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi 	echo -n "Writing beyond end of sysctl ... "	set_orig	dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi 	echo -n "Writing sysctl with multiple long writes ... "	set_orig	(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \		dd of="${TARGET}" bs=50 2>/dev/null	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc} # Your test must accept digits 3 and 4 to use thisrun_limit_digit(){	echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ..."	reset_vals 	LIMIT=$((MAX_DIGITS -1))	TEST_STR="3"	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \		dd of="${TARGET}" 2>/dev/null 	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Checking passing PAGE_SIZE of spaces fails on write ..."	reset_vals 	LIMIT=$((MAX_DIGITS))	TEST_STR="4"	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \		dd of="${TARGET}" 2>/dev/null 	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc} # You are using an intrun_limit_digit_int(){	echo -n "Testing INT_MAX works ..."	reset_vals	TEST_STR="$INT_MAX"	echo -n $TEST_STR > $TARGET 	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing INT_MAX + 1 will fail as expected..."	reset_vals	let TEST_STR=$INT_MAX+1	echo -n $TEST_STR > $TARGET 2> /dev/null 	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing negative values will work as expected..."	reset_vals	TEST_STR="-3"	echo -n $TEST_STR > $TARGET 2> /dev/null	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc} # You used an int arrayrun_limit_digit_int_array(){	echo -n "Testing array works as expected ... "	TEST_STR="4 3 2 1"	echo -n $TEST_STR > $TARGET 	if ! verify_diff_w "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing skipping trailing array elements works ... "	# Do not reset_vals, carry on the values from the last test.	# If we only echo in two digits the last two are left intact	TEST_STR="100 101"	echo -n $TEST_STR > $TARGET	# After we echo in, to help diff we need to set on TEST_STR what	# we expect the result to be.	TEST_STR="100 101 2 1" 	if ! verify_diff_w "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing PAGE_SIZE limit on array works ... "	# Do not reset_vals, carry on the values from the last test.	# Even if you use an int array, you are still restricted to	# MAX_DIGITS, this is a known limitation. Test limit works.	LIMIT=$((MAX_DIGITS -1))	TEST_STR="9"	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \		dd of="${TARGET}" 2>/dev/null 	TEST_STR="9 101 2 1"	if ! verify_diff_w "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "	# Do not reset_vals, carry on the values from the last test.	# Now go over limit.	LIMIT=$((MAX_DIGITS))	TEST_STR="7"	(perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \		dd of="${TARGET}" 2>/dev/null 	TEST_STR="7 101 2 1"	if verify_diff_w "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc} # You are using an unsigned intrun_limit_digit_uint(){	echo -n "Testing UINT_MAX works ..."	reset_vals	TEST_STR="$UINT_MAX"	echo -n $TEST_STR > $TARGET 	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing UINT_MAX + 1 will fail as expected..."	reset_vals	TEST_STR=$(($UINT_MAX+1))	echo -n $TEST_STR > $TARGET 2> /dev/null 	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc 	echo -n "Testing negative values will not work as expected ..."	reset_vals	TEST_STR="-3"	echo -n $TEST_STR > $TARGET 2> /dev/null 	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi	test_rc} run_stringtests(){	echo -n "Writing entire sysctl in short writes ... "	set_orig	dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null	if ! verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi 	echo -n "Writing middle of sysctl after unsynchronized seek ... "	set_test	dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null	if verify "${TARGET}"; then		echo "FAIL" >&2		rc=1	else		echo "ok"	fi 	echo -n "Checking sysctl maxlen is at least $MAXLEN ... "	set_orig

Lines 1–500 of 774.