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