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