Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
0003 #
0004 # This program is free software; you can redistribute it and/or modify it
0005 # under the terms of the GNU General Public License as published by the Free
0006 # Software Foundation; either version 2 of the License, or at your option any
0007 # later version; or, when distributed separately from the Linux kernel or
0008 # when incorporated into other software packages, subject to the following
0009 # license:
0010 #
0011 # This program is free software; you can redistribute it and/or modify it
0012 # under the terms of copyleft-next (version 0.3.1 or later) as published
0013 # at http://copyleft-next.org/.
0014 
0015 # This performs a series tests against the proc sysctl interface.
0016 
0017 # Kselftest framework requirement - SKIP code is 4.
0018 ksft_skip=4
0019 
0020 TEST_NAME="sysctl"
0021 TEST_DRIVER="test_${TEST_NAME}"
0022 TEST_DIR=$(dirname $0)
0023 TEST_FILE=$(mktemp)
0024 
0025 # This represents
0026 #
0027 # TEST_ID:TEST_COUNT:ENABLED:TARGET
0028 #
0029 # TEST_ID: is the test id number
0030 # TEST_COUNT: number of times we should run the test
0031 # ENABLED: 1 if enabled, 0 otherwise
0032 # TARGET: test target file required on the test_sysctl module
0033 #
0034 # Once these are enabled please leave them as-is. Write your own test,
0035 # we have tons of space.
0036 ALL_TESTS="0001:1:1:int_0001"
0037 ALL_TESTS="$ALL_TESTS 0002:1:1:string_0001"
0038 ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002"
0039 ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001"
0040 ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003"
0041 ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001"
0042 ALL_TESTS="$ALL_TESTS 0007:1:1:boot_int"
0043 ALL_TESTS="$ALL_TESTS 0008:1:1:match_int"
0044 
0045 function allow_user_defaults()
0046 {
0047         if [ -z $DIR ]; then
0048                 DIR="/sys/module/test_sysctl/"
0049         fi
0050         if [ -z $DEFAULT_NUM_TESTS ]; then
0051                 DEFAULT_NUM_TESTS=50
0052         fi
0053         if [ -z $SYSCTL ]; then
0054                 SYSCTL="/proc/sys/debug/test_sysctl"
0055         fi
0056         if [ -z $PROD_SYSCTL ]; then
0057                 PROD_SYSCTL="/proc/sys"
0058         fi
0059         if [ -z $WRITES_STRICT ]; then
0060                 WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"
0061         fi
0062 }
0063 
0064 function check_production_sysctl_writes_strict()
0065 {
0066         echo -n "Checking production write strict setting ... "
0067         if [ ! -e ${WRITES_STRICT} ]; then
0068                 echo "FAIL, but skip in case of old kernel" >&2
0069         else
0070                 old_strict=$(cat ${WRITES_STRICT})
0071                 if [ "$old_strict" = "1" ]; then
0072                         echo "ok"
0073                 else
0074                         echo "FAIL, strict value is 0 but force to 1 to continue" >&2
0075                         echo "1" > ${WRITES_STRICT}
0076                 fi
0077         fi
0078 
0079         if [ -z $PAGE_SIZE ]; then
0080                 PAGE_SIZE=$(getconf PAGESIZE)
0081         fi
0082         if [ -z $MAX_DIGITS ]; then
0083                 MAX_DIGITS=$(($PAGE_SIZE/8))
0084         fi
0085         if [ -z $INT_MAX ]; then
0086                 INT_MAX=$(getconf INT_MAX)
0087         fi
0088         if [ -z $UINT_MAX ]; then
0089                 UINT_MAX=$(getconf UINT_MAX)
0090         fi
0091 }
0092 
0093 test_reqs()
0094 {
0095         uid=$(id -u)
0096         if [ $uid -ne 0 ]; then
0097                 echo $msg must be run as root >&2
0098                 exit $ksft_skip
0099         fi
0100 
0101         if ! which perl 2> /dev/null > /dev/null; then
0102                 echo "$0: You need perl installed"
0103                 exit $ksft_skip
0104         fi
0105         if ! which getconf 2> /dev/null > /dev/null; then
0106                 echo "$0: You need getconf installed"
0107                 exit $ksft_skip
0108         fi
0109         if ! which diff 2> /dev/null > /dev/null; then
0110                 echo "$0: You need diff installed"
0111                 exit $ksft_skip
0112         fi
0113 }
0114 
0115 function load_req_mod()
0116 {
0117         if [ ! -d $SYSCTL ]; then
0118                 if ! modprobe -q -n $TEST_DRIVER; then
0119                         echo "$0: module $TEST_DRIVER not found [SKIP]"
0120                         echo "You must set CONFIG_TEST_SYSCTL=m in your kernel" >&2
0121                         exit $ksft_skip
0122                 fi
0123                 modprobe $TEST_DRIVER
0124                 if [ $? -ne 0 ]; then
0125                         echo "$0: modprobe $TEST_DRIVER failed."
0126                         exit
0127                 fi
0128         fi
0129 }
0130 
0131 reset_vals()
0132 {
0133         VAL=""
0134         TRIGGER=$(basename ${TARGET})
0135         case "$TRIGGER" in
0136                 int_0001)
0137                         VAL="60"
0138                         ;;
0139                 int_0002)
0140                         VAL="1"
0141                         ;;
0142                 uint_0001)
0143                         VAL="314"
0144                         ;;
0145                 string_0001)
0146                         VAL="(none)"
0147                         ;;
0148                 bitmap_0001)
0149                         VAL=""
0150                         ;;
0151                 *)
0152                         ;;
0153         esac
0154         echo -n $VAL > $TARGET
0155 }
0156 
0157 set_orig()
0158 {
0159         if [ ! -z $TARGET ] && [ ! -z $ORIG ]; then
0160                 if [ -f ${TARGET} ]; then
0161                         echo "${ORIG}" > "${TARGET}"
0162                 fi
0163         fi
0164 }
0165 
0166 set_test()
0167 {
0168         echo "${TEST_STR}" > "${TARGET}"
0169 }
0170 
0171 verify()
0172 {
0173         local seen
0174         seen=$(cat "$1")
0175         if [ "${seen}" != "${TEST_STR}" ]; then
0176                 return 1
0177         fi
0178         return 0
0179 }
0180 
0181 # proc files get read a page at a time, which can confuse diff,
0182 # and get you incorrect results on proc files with long data. To use
0183 # diff against them you must first extract the output to a file, and
0184 # then compare against that file.
0185 verify_diff_proc_file()
0186 {
0187         TMP_DUMP_FILE=$(mktemp)
0188         cat $1 > $TMP_DUMP_FILE
0189 
0190         if ! diff -w -q $TMP_DUMP_FILE $2; then
0191                 return 1
0192         else
0193                 return 0
0194         fi
0195 }
0196 
0197 verify_diff_w()
0198 {
0199         echo "$TEST_STR" | diff -q -w -u - $1 > /dev/null
0200         return $?
0201 }
0202 
0203 test_rc()
0204 {
0205         if [[ $rc != 0 ]]; then
0206                 echo "Failed test, return value: $rc" >&2
0207                 exit $rc
0208         fi
0209 }
0210 
0211 test_finish()
0212 {
0213         set_orig
0214         rm -f "${TEST_FILE}"
0215 
0216         if [ ! -z ${old_strict} ]; then
0217                 echo ${old_strict} > ${WRITES_STRICT}
0218         fi
0219         exit $rc
0220 }
0221 
0222 run_numerictests()
0223 {
0224         echo "== Testing sysctl behavior against ${TARGET} =="
0225 
0226         rc=0
0227 
0228         echo -n "Writing test file ... "
0229         echo "${TEST_STR}" > "${TEST_FILE}"
0230         if ! verify "${TEST_FILE}"; then
0231                 echo "FAIL" >&2
0232                 exit 1
0233         else
0234                 echo "ok"
0235         fi
0236 
0237         echo -n "Checking sysctl is not set to test value ... "
0238         if verify "${TARGET}"; then
0239                 echo "FAIL" >&2
0240                 exit 1
0241         else
0242                 echo "ok"
0243         fi
0244 
0245         echo -n "Writing sysctl from shell ... "
0246         set_test
0247         if ! verify "${TARGET}"; then
0248                 echo "FAIL" >&2
0249                 exit 1
0250         else
0251                 echo "ok"
0252         fi
0253 
0254         echo -n "Resetting sysctl to original value ... "
0255         set_orig
0256         if verify "${TARGET}"; then
0257                 echo "FAIL" >&2
0258                 exit 1
0259         else
0260                 echo "ok"
0261         fi
0262 
0263         # Now that we've validated the sanity of "set_test" and "set_orig",
0264         # we can use those functions to set starting states before running
0265         # specific behavioral tests.
0266 
0267         echo -n "Writing entire sysctl in single write ... "
0268         set_orig
0269         dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
0270         if ! verify "${TARGET}"; then
0271                 echo "FAIL" >&2
0272                 rc=1
0273         else
0274                 echo "ok"
0275         fi
0276 
0277         echo -n "Writing middle of sysctl after synchronized seek ... "
0278         set_test
0279         dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
0280         if ! verify "${TARGET}"; then
0281                 echo "FAIL" >&2
0282                 rc=1
0283         else
0284                 echo "ok"
0285         fi
0286 
0287         echo -n "Writing beyond end of sysctl ... "
0288         set_orig
0289         dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
0290         if verify "${TARGET}"; then
0291                 echo "FAIL" >&2
0292                 rc=1
0293         else
0294                 echo "ok"
0295         fi
0296 
0297         echo -n "Writing sysctl with multiple long writes ... "
0298         set_orig
0299         (perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
0300                 dd of="${TARGET}" bs=50 2>/dev/null
0301         if verify "${TARGET}"; then
0302                 echo "FAIL" >&2
0303                 rc=1
0304         else
0305                 echo "ok"
0306         fi
0307         test_rc
0308 }
0309 
0310 check_failure()
0311 {
0312         echo -n "Testing that $1 fails as expected..."
0313         reset_vals
0314         TEST_STR="$1"
0315         orig="$(cat $TARGET)"
0316         echo -n "$TEST_STR" > $TARGET 2> /dev/null
0317 
0318         # write should fail and $TARGET should retain its original value
0319         if [ $? = 0 ] || [ "$(cat $TARGET)" != "$orig" ]; then
0320                 echo "FAIL" >&2
0321                 rc=1
0322         else
0323                 echo "ok"
0324         fi
0325         test_rc
0326 }
0327 
0328 run_wideint_tests()
0329 {
0330         # sysctl conversion functions receive a boolean sign and ulong
0331         # magnitude; here we list the magnitudes we want to test (each of
0332         # which will be tested in both positive and negative forms).  Since
0333         # none of these values fit in 32 bits, writing them to an int- or
0334         # uint-typed sysctl should fail.
0335         local magnitudes=(
0336                 # common boundary-condition values (zero, +1, -1, INT_MIN,
0337                 # and INT_MAX respectively) if truncated to lower 32 bits
0338                 # (potential for being falsely deemed in range)
0339                 0x0000000100000000
0340                 0x0000000100000001
0341                 0x00000001ffffffff
0342                 0x0000000180000000
0343                 0x000000017fffffff
0344 
0345                 # these look like negatives, but without a leading '-' are
0346                 # actually large positives (should be rejected as above
0347                 # despite being zero/+1/-1/INT_MIN/INT_MAX in the lower 32)
0348                 0xffffffff00000000
0349                 0xffffffff00000001
0350                 0xffffffffffffffff
0351                 0xffffffff80000000
0352                 0xffffffff7fffffff
0353         )
0354 
0355         for sign in '' '-'; do
0356                 for mag in "${magnitudes[@]}"; do
0357                         check_failure "${sign}${mag}"
0358                 done
0359         done
0360 }
0361 
0362 # Your test must accept digits 3 and 4 to use this
0363 run_limit_digit()
0364 {
0365         echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ..."
0366         reset_vals
0367 
0368         LIMIT=$((MAX_DIGITS -1))
0369         TEST_STR="3"
0370         (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
0371                 dd of="${TARGET}" 2>/dev/null
0372 
0373         if ! verify "${TARGET}"; then
0374                 echo "FAIL" >&2
0375                 rc=1
0376         else
0377                 echo "ok"
0378         fi
0379         test_rc
0380 
0381         echo -n "Checking passing PAGE_SIZE of spaces fails on write ..."
0382         reset_vals
0383 
0384         LIMIT=$((MAX_DIGITS))
0385         TEST_STR="4"
0386         (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
0387                 dd of="${TARGET}" 2>/dev/null
0388 
0389         if verify "${TARGET}"; then
0390                 echo "FAIL" >&2
0391                 rc=1
0392         else
0393                 echo "ok"
0394         fi
0395         test_rc
0396 }
0397 
0398 # You are using an int
0399 run_limit_digit_int()
0400 {
0401         echo -n "Testing INT_MAX works ..."
0402         reset_vals
0403         TEST_STR="$INT_MAX"
0404         echo -n $TEST_STR > $TARGET
0405 
0406         if ! verify "${TARGET}"; then
0407                 echo "FAIL" >&2
0408                 rc=1
0409         else
0410                 echo "ok"
0411         fi
0412         test_rc
0413 
0414         echo -n "Testing INT_MAX + 1 will fail as expected..."
0415         reset_vals
0416         let TEST_STR=$INT_MAX+1
0417         echo -n $TEST_STR > $TARGET 2> /dev/null
0418 
0419         if verify "${TARGET}"; then
0420                 echo "FAIL" >&2
0421                 rc=1
0422         else
0423                 echo "ok"
0424         fi
0425         test_rc
0426 
0427         echo -n "Testing negative values will work as expected..."
0428         reset_vals
0429         TEST_STR="-3"
0430         echo -n $TEST_STR > $TARGET 2> /dev/null
0431         if ! verify "${TARGET}"; then
0432                 echo "FAIL" >&2
0433                 rc=1
0434         else
0435                 echo "ok"
0436         fi
0437         test_rc
0438 }
0439 
0440 # You used an int array
0441 run_limit_digit_int_array()
0442 {
0443         echo -n "Testing array works as expected ... "
0444         TEST_STR="4 3 2 1"
0445         echo -n $TEST_STR > $TARGET
0446 
0447         if ! verify_diff_w "${TARGET}"; then
0448                 echo "FAIL" >&2
0449                 rc=1
0450         else
0451                 echo "ok"
0452         fi
0453         test_rc
0454 
0455         echo -n "Testing skipping trailing array elements works ... "
0456         # Do not reset_vals, carry on the values from the last test.
0457         # If we only echo in two digits the last two are left intact
0458         TEST_STR="100 101"
0459         echo -n $TEST_STR > $TARGET
0460         # After we echo in, to help diff we need to set on TEST_STR what
0461         # we expect the result to be.
0462         TEST_STR="100 101 2 1"
0463 
0464         if ! verify_diff_w "${TARGET}"; then
0465                 echo "FAIL" >&2
0466                 rc=1
0467         else
0468                 echo "ok"
0469         fi
0470         test_rc
0471 
0472         echo -n "Testing PAGE_SIZE limit on array works ... "
0473         # Do not reset_vals, carry on the values from the last test.
0474         # Even if you use an int array, you are still restricted to
0475         # MAX_DIGITS, this is a known limitation. Test limit works.
0476         LIMIT=$((MAX_DIGITS -1))
0477         TEST_STR="9"
0478         (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
0479                 dd of="${TARGET}" 2>/dev/null
0480 
0481         TEST_STR="9 101 2 1"
0482         if ! verify_diff_w "${TARGET}"; then
0483                 echo "FAIL" >&2
0484                 rc=1
0485         else
0486                 echo "ok"
0487         fi
0488         test_rc
0489 
0490         echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "
0491         # Do not reset_vals, carry on the values from the last test.
0492         # Now go over limit.
0493         LIMIT=$((MAX_DIGITS))
0494         TEST_STR="7"
0495         (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
0496                 dd of="${TARGET}" 2>/dev/null
0497 
0498         TEST_STR="7 101 2 1"
0499         if verify_diff_w "${TARGET}"; then
0500                 echo "FAIL" >&2
0501                 rc=1
0502         else
0503                 echo "ok"
0504         fi
0505         test_rc
0506 }
0507 
0508 # You are using an unsigned int
0509 run_limit_digit_uint()
0510 {
0511         echo -n "Testing UINT_MAX works ..."
0512         reset_vals
0513         TEST_STR="$UINT_MAX"
0514         echo -n $TEST_STR > $TARGET
0515 
0516         if ! verify "${TARGET}"; then
0517                 echo "FAIL" >&2
0518                 rc=1
0519         else
0520                 echo "ok"
0521         fi
0522         test_rc
0523 
0524         echo -n "Testing UINT_MAX + 1 will fail as expected..."
0525         reset_vals
0526         TEST_STR=$(($UINT_MAX+1))
0527         echo -n $TEST_STR > $TARGET 2> /dev/null
0528 
0529         if verify "${TARGET}"; then
0530                 echo "FAIL" >&2
0531                 rc=1
0532         else
0533                 echo "ok"
0534         fi
0535         test_rc
0536 
0537         echo -n "Testing negative values will not work as expected ..."
0538         reset_vals
0539         TEST_STR="-3"
0540         echo -n $TEST_STR > $TARGET 2> /dev/null
0541 
0542         if verify "${TARGET}"; then
0543                 echo "FAIL" >&2
0544                 rc=1
0545         else
0546                 echo "ok"
0547         fi
0548         test_rc
0549 }
0550 
0551 run_stringtests()
0552 {
0553         echo -n "Writing entire sysctl in short writes ... "
0554         set_orig
0555         dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
0556         if ! verify "${TARGET}"; then
0557                 echo "FAIL" >&2
0558                 rc=1
0559         else
0560                 echo "ok"
0561         fi
0562 
0563         echo -n "Writing middle of sysctl after unsynchronized seek ... "
0564         set_test
0565         dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
0566         if verify "${TARGET}"; then
0567                 echo "FAIL" >&2
0568                 rc=1
0569         else
0570                 echo "ok"
0571         fi
0572 
0573         echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
0574         set_orig
0575         perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
0576                 dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
0577         if ! grep -q B "${TARGET}"; then
0578                 echo "FAIL" >&2
0579                 rc=1
0580         else
0581                 echo "ok"
0582         fi
0583 
0584         echo -n "Checking sysctl keeps original string on overflow append ... "
0585         set_orig
0586         perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
0587                 dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
0588         if grep -q B "${TARGET}"; then
0589                 echo "FAIL" >&2
0590                 rc=1
0591         else
0592                 echo "ok"
0593         fi
0594 
0595         echo -n "Checking sysctl stays NULL terminated on write ... "
0596         set_orig
0597         perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
0598                 dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
0599         if grep -q B "${TARGET}"; then
0600                 echo "FAIL" >&2
0601                 rc=1
0602         else
0603                 echo "ok"
0604         fi
0605 
0606         echo -n "Checking sysctl stays NULL terminated on overwrite ... "
0607         set_orig
0608         perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
0609                 dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
0610         if grep -q B "${TARGET}"; then
0611                 echo "FAIL" >&2
0612                 rc=1
0613         else
0614                 echo "ok"
0615         fi
0616 
0617         test_rc
0618 }
0619 
0620 target_exists()
0621 {
0622         TARGET="${SYSCTL}/$1"
0623         TEST_ID="$2"
0624 
0625         if [ ! -f ${TARGET} ] ; then
0626                 echo "Target for test $TEST_ID: $TARGET not exist, skipping test ..."
0627                 return 0
0628         fi
0629         return 1
0630 }
0631 
0632 run_bitmaptest() {
0633         # Total length of bitmaps string to use, a bit under
0634         # the maximum input size of the test node
0635         LENGTH=$((RANDOM % 65000))
0636 
0637         # First bit to set
0638         BIT=$((RANDOM % 1024))
0639 
0640         # String containing our list of bits to set
0641         TEST_STR=$BIT
0642 
0643         # build up the string
0644         while [ "${#TEST_STR}" -le "$LENGTH" ]; do
0645                 # Make sure next entry is discontiguous,
0646                 # skip ahead at least 2
0647                 BIT=$((BIT + $((2 + RANDOM % 10))))
0648 
0649                 # Add new bit to the list
0650                 TEST_STR="${TEST_STR},${BIT}"
0651 
0652                 # Randomly make it a range
0653                 if [ "$((RANDOM % 2))" -eq "1" ]; then
0654                         RANGE_END=$((BIT + $((1 + RANDOM % 10))))
0655                         TEST_STR="${TEST_STR}-${RANGE_END}"
0656                         BIT=$RANGE_END
0657                 fi
0658         done
0659 
0660         echo -n "Checking bitmap handler... "
0661         TEST_FILE=$(mktemp)
0662         echo -n "$TEST_STR" > $TEST_FILE
0663 
0664         cat $TEST_FILE > $TARGET 2> /dev/null
0665         if [ $? -ne 0 ]; then
0666                 echo "FAIL" >&2
0667                 rc=1
0668                 test_rc
0669         fi
0670 
0671         if ! verify_diff_proc_file "$TARGET" "$TEST_FILE"; then
0672                 echo "FAIL" >&2
0673                 rc=1
0674         else
0675                 echo "ok"
0676                 rc=0
0677         fi
0678         test_rc
0679 }
0680 
0681 sysctl_test_0001()
0682 {
0683         TARGET="${SYSCTL}/$(get_test_target 0001)"
0684         reset_vals
0685         ORIG=$(cat "${TARGET}")
0686         TEST_STR=$(( $ORIG + 1 ))
0687 
0688         run_numerictests
0689         run_wideint_tests
0690         run_limit_digit
0691 }
0692 
0693 sysctl_test_0002()
0694 {
0695         TARGET="${SYSCTL}/$(get_test_target 0002)"
0696         reset_vals
0697         ORIG=$(cat "${TARGET}")
0698         TEST_STR="Testing sysctl"
0699         # Only string sysctls support seeking/appending.
0700         MAXLEN=65
0701 
0702         run_numerictests
0703         run_stringtests
0704 }
0705 
0706 sysctl_test_0003()
0707 {
0708         TARGET="${SYSCTL}/$(get_test_target 0003)"
0709         reset_vals
0710         ORIG=$(cat "${TARGET}")
0711         TEST_STR=$(( $ORIG + 1 ))
0712 
0713         run_numerictests
0714         run_wideint_tests
0715         run_limit_digit
0716         run_limit_digit_int
0717 }
0718 
0719 sysctl_test_0004()
0720 {
0721         TARGET="${SYSCTL}/$(get_test_target 0004)"
0722         reset_vals
0723         ORIG=$(cat "${TARGET}")
0724         TEST_STR=$(( $ORIG + 1 ))
0725 
0726         run_numerictests
0727         run_wideint_tests
0728         run_limit_digit
0729         run_limit_digit_uint
0730 }
0731 
0732 sysctl_test_0005()
0733 {
0734         TARGET="${SYSCTL}/$(get_test_target 0005)"
0735         reset_vals
0736         ORIG=$(cat "${TARGET}")
0737 
0738         run_limit_digit_int_array
0739 }
0740 
0741 sysctl_test_0006()
0742 {
0743         TARGET="${SYSCTL}/bitmap_0001"
0744         reset_vals
0745         ORIG=""
0746         run_bitmaptest
0747 }
0748 
0749 sysctl_test_0007()
0750 {
0751         TARGET="${SYSCTL}/boot_int"
0752         if [ ! -f $TARGET ]; then
0753                 echo "Skipping test for $TARGET as it is not present ..."
0754                 return $ksft_skip
0755         fi
0756 
0757         if [ -d $DIR ]; then
0758                 echo "Boot param test only possible sysctl_test is built-in, not module:"
0759                 cat $TEST_DIR/config >&2
0760                 return $ksft_skip
0761         fi
0762 
0763         echo -n "Testing if $TARGET is set to 1 ..."
0764         ORIG=$(cat "${TARGET}")
0765 
0766         if [ x$ORIG = "x1" ]; then
0767                 echo "ok"
0768                 return 0
0769         fi
0770         echo "FAIL"
0771         echo "Checking if /proc/cmdline contains setting of the expected parameter ..."
0772         if [ ! -f /proc/cmdline ]; then
0773                 echo "/proc/cmdline does not exist, test inconclusive"
0774                 return 0
0775         fi
0776 
0777         FOUND=$(grep -c "sysctl[./]debug[./]test_sysctl[./]boot_int=1" /proc/cmdline)
0778         if [ $FOUND = "1" ]; then
0779                 echo "Kernel param found but $TARGET is not 1, TEST FAILED"
0780                 rc=1
0781                 test_rc
0782         fi
0783 
0784         echo "Skipping test, expected kernel parameter missing."
0785         echo "To perform this test, make sure kernel is booted with parameter: sysctl.debug.test_sysctl.boot_int=1"
0786         return $ksft_skip
0787 }
0788 
0789 sysctl_test_0008()
0790 {
0791         TARGET="${SYSCTL}/match_int"
0792         if [ ! -f $TARGET ]; then
0793                 echo "Skipping test for $TARGET as it is not present ..."
0794                 return $ksft_skip
0795         fi
0796 
0797         echo -n "Testing if $TARGET is matched in kernel"
0798         ORIG_VALUE=$(cat "${TARGET}")
0799 
0800         if [ $ORIG_VALUE -ne 1 ]; then
0801                 echo "TEST FAILED"
0802                 rc=1
0803                 test_rc
0804         fi
0805 
0806         echo "ok"
0807         return 0
0808 }
0809 
0810 list_tests()
0811 {
0812         echo "Test ID list:"
0813         echo
0814         echo "TEST_ID x NUM_TEST"
0815         echo "TEST_ID:   Test ID"
0816         echo "NUM_TESTS: Number of recommended times to run the test"
0817         echo
0818         echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
0819         echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
0820         echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
0821         echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
0822         echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
0823         echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()"
0824         echo "0007 x $(get_test_count 0007) - tests setting sysctl from kernel boot param"
0825         echo "0008 x $(get_test_count 0008) - tests sysctl macro values match"
0826 }
0827 
0828 usage()
0829 {
0830         NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
0831         let NUM_TESTS=$NUM_TESTS+1
0832         MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
0833         echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
0834         echo "           [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
0835         echo "           [ all ] [ -h | --help ] [ -l ]"
0836         echo ""
0837         echo "Valid tests: 0001-$MAX_TEST"
0838         echo ""
0839         echo "    all     Runs all tests (default)"
0840         echo "    -t      Run test ID the number amount of times is recommended"
0841         echo "    -w      Watch test ID run until it runs into an error"
0842         echo "    -c      Run test ID once"
0843         echo "    -s      Run test ID x test-count number of times"
0844         echo "    -l      List all test ID list"
0845         echo " -h|--help  Help"
0846         echo
0847         echo "If an error every occurs execution will immediately terminate."
0848         echo "If you are adding a new test try using -w <test-ID> first to"
0849         echo "make sure the test passes a series of tests."
0850         echo
0851         echo Example uses:
0852         echo
0853         echo "$TEST_NAME.sh            -- executes all tests"
0854         echo "$TEST_NAME.sh -t 0002    -- Executes test ID 0002 number of times is recomended"
0855         echo "$TEST_NAME.sh -w 0002    -- Watch test ID 0002 run until an error occurs"
0856         echo "$TEST_NAME.sh -s 0002    -- Run test ID 0002 once"
0857         echo "$TEST_NAME.sh -c 0002 3  -- Run test ID 0002 three times"
0858         echo
0859         list_tests
0860         exit 1
0861 }
0862 
0863 function test_num()
0864 {
0865         re='^[0-9]+$'
0866         if ! [[ $1 =~ $re ]]; then
0867                 usage
0868         fi
0869 }
0870 
0871 function get_test_count()
0872 {
0873         test_num $1
0874         TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
0875         echo ${TEST_DATA} | awk -F":" '{print $2}'
0876 }
0877 
0878 function get_test_enabled()
0879 {
0880         test_num $1
0881         TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
0882         echo ${TEST_DATA} | awk -F":" '{print $3}'
0883 }
0884 
0885 function get_test_target()
0886 {
0887         test_num $1
0888         TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
0889         echo ${TEST_DATA} | awk -F":" '{print $4}'
0890 }
0891 
0892 function run_all_tests()
0893 {
0894         for i in $ALL_TESTS ; do
0895                 TEST_ID=${i%:*:*:*}
0896                 ENABLED=$(get_test_enabled $TEST_ID)
0897                 TEST_COUNT=$(get_test_count $TEST_ID)
0898                 TEST_TARGET=$(get_test_target $TEST_ID)
0899                 if target_exists $TEST_TARGET $TEST_ID; then
0900                         continue
0901                 fi
0902                 if [[ $ENABLED -eq "1" ]]; then
0903                         test_case $TEST_ID $TEST_COUNT $TEST_TARGET
0904                 fi
0905         done
0906 }
0907 
0908 function watch_log()
0909 {
0910         if [ $# -ne 3 ]; then
0911                 clear
0912         fi
0913         date
0914         echo "Running test: $2 - run #$1"
0915 }
0916 
0917 function watch_case()
0918 {
0919         i=0
0920         while [ 1 ]; do
0921 
0922                 if [ $# -eq 1 ]; then
0923                         test_num $1
0924                         watch_log $i ${TEST_NAME}_test_$1
0925                         ${TEST_NAME}_test_$1
0926                 else
0927                         watch_log $i all
0928                         run_all_tests
0929                 fi
0930                 let i=$i+1
0931         done
0932 }
0933 
0934 function test_case()
0935 {
0936         NUM_TESTS=$2
0937 
0938         i=0
0939 
0940         if target_exists $3 $1; then
0941                 continue
0942         fi
0943 
0944         while [ $i -lt $NUM_TESTS ]; do
0945                 test_num $1
0946                 watch_log $i ${TEST_NAME}_test_$1 noclear
0947                 RUN_TEST=${TEST_NAME}_test_$1
0948                 $RUN_TEST
0949                 let i=$i+1
0950         done
0951 }
0952 
0953 function parse_args()
0954 {
0955         if [ $# -eq 0 ]; then
0956                 run_all_tests
0957         else
0958                 if [[ "$1" = "all" ]]; then
0959                         run_all_tests
0960                 elif [[ "$1" = "-w" ]]; then
0961                         shift
0962                         watch_case $@
0963                 elif [[ "$1" = "-t" ]]; then
0964                         shift
0965                         test_num $1
0966                         test_case $1 $(get_test_count $1) $(get_test_target $1)
0967                 elif [[ "$1" = "-c" ]]; then
0968                         shift
0969                         test_num $1
0970                         test_num $2
0971                         test_case $1 $2 $(get_test_target $1)
0972                 elif [[ "$1" = "-s" ]]; then
0973                         shift
0974                         test_case $1 1 $(get_test_target $1)
0975                 elif [[ "$1" = "-l" ]]; then
0976                         list_tests
0977                 elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
0978                         usage
0979                 else
0980                         usage
0981                 fi
0982         fi
0983 }
0984 
0985 test_reqs
0986 allow_user_defaults
0987 check_production_sysctl_writes_strict
0988 load_req_mod
0989 
0990 trap "test_finish" EXIT
0991 
0992 parse_args $@
0993 
0994 exit 0