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 1070