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