Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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