aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2017-07-14 17:50:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-14 18:05:13 -0400
commitd9c6a72d6fa29d3a7999dda726577e5d1fccafa5 (patch)
tree5ebd3b4bf7ba6d7b79640b68edf784e30c0c6801 /tools
parent062b87406d0d73b3894b562dc3067d9ea760bd3e (diff)
kmod: add test driver to stress test the module loader
This adds a new stress test driver for kmod: the kernel module loader. The new stress test driver, test_kmod, is only enabled as a module right now. It should be possible to load this as built-in and load tests early (refer to the force_init_test module parameter), however since a lot of test can get a system out of memory fast we leave this disabled for now. Using a system with 1024 MiB of RAM can *easily* get your kernel OOM fast with this test driver. The test_kmod driver exposes API knobs for us to fine tune simple request_module() and get_fs_type() calls. Since these API calls only allow each one parameter a test driver for these is rather simple. Other factors that can help out test driver though are the number of calls we issue and knowing current limitations of each. This exposes configuration as much as possible through userspace to be able to build tests directly from userspace. Since it allows multiple misc devices its will eventually (once we add a knob to let us create new devices at will) also be possible to perform more tests in parallel, provided you have enough memory. We only enable tests we know work as of right now. Demo screenshots: # tools/testing/selftests/kmod/kmod.sh kmod_test_0001_driver: OK! - loading kmod test kmod_test_0001_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND kmod_test_0001_fs: OK! - loading kmod test kmod_test_0001_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL kmod_test_0002_driver: OK! - loading kmod test kmod_test_0002_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND kmod_test_0002_fs: OK! - loading kmod test kmod_test_0002_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL kmod_test_0003: OK! - loading kmod test kmod_test_0003: OK! - Return value: 0 (SUCCESS), expected SUCCESS kmod_test_0004: OK! - loading kmod test kmod_test_0004: OK! - Return value: 0 (SUCCESS), expected SUCCESS kmod_test_0005: OK! - loading kmod test kmod_test_0005: OK! - Return value: 0 (SUCCESS), expected SUCCESS kmod_test_0006: OK! - loading kmod test kmod_test_0006: OK! - Return value: 0 (SUCCESS), expected SUCCESS kmod_test_0005: OK! - loading kmod test kmod_test_0005: OK! - Return value: 0 (SUCCESS), expected SUCCESS kmod_test_0006: OK! - loading kmod test kmod_test_0006: OK! - Return value: 0 (SUCCESS), expected SUCCESS XXX: add test restult for 0007 Test completed You can also request for specific tests: # tools/testing/selftests/kmod/kmod.sh -t 0001 kmod_test_0001_driver: OK! - loading kmod test kmod_test_0001_driver: OK! - Return value: 256 (MODULE_NOT_FOUND), expected MODULE_NOT_FOUND kmod_test_0001_fs: OK! - loading kmod test kmod_test_0001_fs: OK! - Return value: -22 (-EINVAL), expected -EINVAL Test completed Lastly, the current available number of tests: # tools/testing/selftests/kmod/kmod.sh --help Usage: tools/testing/selftests/kmod/kmod.sh [ -t <4-number-digit> ] Valid tests: 0001-0009 0001 - Simple test - 1 thread for empty string 0002 - Simple test - 1 thread for modules/filesystems that do not exist 0003 - Simple test - 1 thread for get_fs_type() only 0004 - Simple test - 2 threads for get_fs_type() only 0005 - multithreaded tests with default setup - request_module() only 0006 - multithreaded tests with default setup - get_fs_type() only 0007 - multithreaded tests with default setup test request_module() and get_fs_type() 0008 - multithreaded - push kmod_concurrent over max_modprobes for request_module() 0009 - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type() The following test cases currently fail, as such they are not currently enabled by default: # tools/testing/selftests/kmod/kmod.sh -t 0008 # tools/testing/selftests/kmod/kmod.sh -t 0009 To be sure to run them as intended please unload both of the modules: o test_module o xfs And ensure they are not loaded on your system prior to testing them. If you use these paritions for your rootfs you can change the default test driver used for get_fs_type() by exporting it into your environment. For example of other test defaults you can override refer to kmod.sh allow_user_defaults(). Behind the scenes this is how we fine tune at a test case prior to hitting a trigger to run it: cat /sys/devices/virtual/misc/test_kmod0/config echo -n "2" > /sys/devices/virtual/misc/test_kmod0/config_test_case echo -n "ext4" > /sys/devices/virtual/misc/test_kmod0/config_test_fs echo -n "80" > /sys/devices/virtual/misc/test_kmod0/config_num_threads cat /sys/devices/virtual/misc/test_kmod0/config echo -n "1" > /sys/devices/virtual/misc/test_kmod0/config_num_threads Finally to trigger: echo -n "1" > /sys/devices/virtual/misc/test_kmod0/trigger_config The kmod.sh script uses the above constructs to build different test cases. A bit of interpretation of the current failures follows, first two premises: a) When request_module() is used userspace figures out an optimized version of module order for us. Once it finds the modules it needs, as per depmod symbol dep map, it will finit_module() the respective modules which are needed for the original request_module() request. b) We have an optimization in place whereby if a kernel uses request_module() on a module already loaded we never bother userspace as the module already is loaded. This is all handled by kernel/kmod.c. A few things to consider to help identify root causes of issues: 0) kmod 19 has a broken heuristic for modules being assumed to be built-in to your kernel and will return 0 even though request_module() failed. Upgrade to a newer version of kmod. 1) A get_fs_type() call for "xfs" will request_module() for "fs-xfs", not for "xfs". The optimization in kernel described in b) fails to catch if we have a lot of consecutive get_fs_type() calls. The reason is the optimization in place does not look for aliases. This means two consecutive get_fs_type() calls will bump kmod_concurrent, whereas request_module() will not. This one explanation why test case 0009 fails at least once for get_fs_type(). 2) If a module fails to load --- for whatever reason (kmod_concurrent limit reached, file not yet present due to rootfs switch, out of memory) we have a period of time during which module request for the same name either with request_module() or get_fs_type() will *also* fail to load even if the file for the module is ready. This explains why *multiple* NULLs are possible on test 0009. 3) finit_module() consumes quite a bit of memory. 4) Filesystems typically also have more dependent modules than other modules, its important to note though that even though a get_fs_type() call does not incur additional kmod_concurrent bumps, since userspace loads dependencies it finds it needs via finit_module_fd(), it *will* take much more memory to load a module with a lot of dependencies. Because of 3) and 4) we will easily run into out of memory failures with certain tests. For instance test 0006 fails on qemu with 1024 MiB of RAM. It panics a box after reaping all userspace processes and still not having enough memory to reap. [arnd@arndb.de: add dependencies for test module] Link: http://lkml.kernel.org/r/20170630154834.3689272-1-arnd@arndb.de Link: http://lkml.kernel.org/r/20170628223155.26472-3-mcgrof@kernel.org Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Cc: Jessica Yu <jeyu@redhat.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Michal Marek <mmarek@suse.com> Cc: Petr Mladek <pmladek@suse.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/kmod/Makefile11
-rw-r--r--tools/testing/selftests/kmod/config7
-rw-r--r--tools/testing/selftests/kmod/kmod.sh635
3 files changed, 653 insertions, 0 deletions
diff --git a/tools/testing/selftests/kmod/Makefile b/tools/testing/selftests/kmod/Makefile
new file mode 100644
index 000000000000..fa2ccc5fb3de
--- /dev/null
+++ b/tools/testing/selftests/kmod/Makefile
@@ -0,0 +1,11 @@
1# Makefile for kmod loading selftests
2
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all:
5
6TEST_PROGS := kmod.sh
7
8include ../lib.mk
9
10# Nothing to clean up.
11clean:
diff --git a/tools/testing/selftests/kmod/config b/tools/testing/selftests/kmod/config
new file mode 100644
index 000000000000..259f4fd6b5e2
--- /dev/null
+++ b/tools/testing/selftests/kmod/config
@@ -0,0 +1,7 @@
1CONFIG_TEST_KMOD=m
2CONFIG_TEST_LKM=m
3CONFIG_XFS_FS=m
4
5# For the module parameter force_init_test is used
6CONFIG_TUN=m
7CONFIG_BTRFS_FS=m
diff --git a/tools/testing/selftests/kmod/kmod.sh b/tools/testing/selftests/kmod/kmod.sh
new file mode 100644
index 000000000000..10196a62ed09
--- /dev/null
+++ b/tools/testing/selftests/kmod/kmod.sh
@@ -0,0 +1,635 @@
1#!/bin/bash
2#
3# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the Free
7# Software Foundation; either version 2 of the License, or at your option any
8# later version; or, when distributed separately from the Linux kernel or
9# when incorporated into other software packages, subject to the following
10# license:
11#
12# This program is free software; you can redistribute it and/or modify it
13# under the terms of copyleft-next (version 0.3.1 or later) as published
14# at http://copyleft-next.org/.
15
16# This is a stress test script for kmod, the kernel module loader. It uses
17# test_kmod which exposes a series of knobs for the API for us so we can
18# tweak each test in userspace rather than in kernelspace.
19#
20# The way kmod works is it uses the kernel's usermode helper API to eventually
21# call /sbin/modprobe. It has a limit of the number of concurrent calls
22# possible. The kernel interface to load modules is request_module(), however
23# mount uses get_fs_type(). Both behave slightly differently, but the
24# differences are important enough to test each call separately. For this
25# reason test_kmod starts by providing tests for both calls.
26#
27# The test driver test_kmod assumes a series of defaults which you can
28# override by exporting to your environment prior running this script.
29# For instance this script assumes you do not have xfs loaded upon boot.
30# If this is false, export DEFAULT_KMOD_FS="ext4" prior to running this
31# script if the filesyste module you don't have loaded upon bootup
32# is ext4 instead. Refer to allow_user_defaults() for a list of user
33# override variables possible.
34#
35# You'll want at least 4 GiB of RAM to expect to run these tests
36# without running out of memory on them. For other requirements refer
37# to test_reqs()
38
39set -e
40
41TEST_NAME="kmod"
42TEST_DRIVER="test_${TEST_NAME}"
43TEST_DIR=$(dirname $0)
44
45# This represents
46#
47# TEST_ID:TEST_COUNT:ENABLED
48#
49# TEST_ID: is the test id number
50# TEST_COUNT: number of times we should run the test
51# ENABLED: 1 if enabled, 0 otherwise
52#
53# Once these are enabled please leave them as-is. Write your own test,
54# we have tons of space.
55ALL_TESTS="0001:3:1"
56ALL_TESTS="$ALL_TESTS 0002:3:1"
57ALL_TESTS="$ALL_TESTS 0003:1:1"
58ALL_TESTS="$ALL_TESTS 0004:1:1"
59ALL_TESTS="$ALL_TESTS 0005:10:1"
60ALL_TESTS="$ALL_TESTS 0006:10:1"
61ALL_TESTS="$ALL_TESTS 0007:5:1"
62
63# Disabled tests:
64#
65# 0008 x 150 - multithreaded - push kmod_concurrent over max_modprobes for request_module()"
66# Current best-effort failure interpretation:
67# Enough module requests get loaded in place fast enough to reach over the
68# max_modprobes limit and trigger a failure -- before we're even able to
69# start processing pending requests.
70ALL_TESTS="$ALL_TESTS 0008:150:0"
71
72# 0009 x 150 - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
73# Current best-effort failure interpretation:
74#
75# get_fs_type() requests modules using aliases as such the optimization in
76# place today to look for already loaded modules will not take effect and
77# we end up requesting a new module to load, this bumps the kmod_concurrent,
78# and in certain circumstances can lead to pushing the kmod_concurrent over
79# the max_modprobe limit.
80#
81# This test fails much easier than test 0008 since the alias optimizations
82# are not in place.
83ALL_TESTS="$ALL_TESTS 0009:150:0"
84
85test_modprobe()
86{
87 if [ ! -d $DIR ]; then
88 echo "$0: $DIR not present" >&2
89 echo "You must have the following enabled in your kernel:" >&2
90 cat $TEST_DIR/config >&2
91 exit 1
92 fi
93}
94
95function allow_user_defaults()
96{
97 if [ -z $DEFAULT_KMOD_DRIVER ]; then
98 DEFAULT_KMOD_DRIVER="test_module"
99 fi
100
101 if [ -z $DEFAULT_KMOD_FS ]; then
102 DEFAULT_KMOD_FS="xfs"
103 fi
104
105 if [ -z $PROC_DIR ]; then
106 PROC_DIR="/proc/sys/kernel/"
107 fi
108
109 if [ -z $MODPROBE_LIMIT ]; then
110 MODPROBE_LIMIT=50
111 fi
112
113 if [ -z $DIR ]; then
114 DIR="/sys/devices/virtual/misc/${TEST_DRIVER}0/"
115 fi
116
117 if [ -z $DEFAULT_NUM_TESTS ]; then
118 DEFAULT_NUM_TESTS=150
119 fi
120
121 MODPROBE_LIMIT_FILE="${PROC_DIR}/kmod-limit"
122}
123
124test_reqs()
125{
126 if ! which modprobe 2> /dev/null > /dev/null; then
127 echo "$0: You need modprobe installed" >&2
128 exit 1
129 fi
130
131 if ! which kmod 2> /dev/null > /dev/null; then
132 echo "$0: You need kmod installed" >&2
133 exit 1
134 fi
135
136 # kmod 19 has a bad bug where it returns 0 when modprobe
137 # gets called *even* if the module was not loaded due to
138 # some bad heuristics. For details see:
139 #
140 # A work around is possible in-kernel but its rather
141 # complex.
142 KMOD_VERSION=$(kmod --version | awk '{print $3}')
143 if [[ $KMOD_VERSION -le 19 ]]; then
144 echo "$0: You need at least kmod 20" >&2
145 echo "kmod <= 19 is buggy, for details see:" >&2
146 echo "http://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/libkmod/libkmod-module.c?id=fd44a98ae2eb5eb32161088954ab21e58e19dfc4" >&2
147 exit 1
148 fi
149
150 uid=$(id -u)
151 if [ $uid -ne 0 ]; then
152 echo $msg must be run as root >&2
153 exit 0
154 fi
155}
156
157function load_req_mod()
158{
159 trap "test_modprobe" EXIT
160
161 if [ ! -d $DIR ]; then
162 # Alanis: "Oh isn't it ironic?"
163 modprobe $TEST_DRIVER
164 fi
165}
166
167test_finish()
168{
169 echo "Test completed"
170}
171
172errno_name_to_val()
173{
174 case "$1" in
175 # kmod calls modprobe and upon of a module not found
176 # modprobe returns just 1... However in the kernel we
177 # *sometimes* see 256...
178 MODULE_NOT_FOUND)
179 echo 256;;
180 SUCCESS)
181 echo 0;;
182 -EPERM)
183 echo -1;;
184 -ENOENT)
185 echo -2;;
186 -EINVAL)
187 echo -22;;
188 -ERR_ANY)
189 echo -123456;;
190 *)
191 echo invalid;;
192 esac
193}
194
195errno_val_to_name()
196 case "$1" in
197 256)
198 echo MODULE_NOT_FOUND;;
199 0)
200 echo SUCCESS;;
201 -1)
202 echo -EPERM;;
203 -2)
204 echo -ENOENT;;
205 -22)
206 echo -EINVAL;;
207 -123456)
208 echo -ERR_ANY;;
209 *)
210 echo invalid;;
211 esac
212
213config_set_test_case_driver()
214{
215 if ! echo -n 1 >$DIR/config_test_case; then
216 echo "$0: Unable to set to test case to driver" >&2
217 exit 1
218 fi
219}
220
221config_set_test_case_fs()
222{
223 if ! echo -n 2 >$DIR/config_test_case; then
224 echo "$0: Unable to set to test case to fs" >&2
225 exit 1
226 fi
227}
228
229config_num_threads()
230{
231 if ! echo -n $1 >$DIR/config_num_threads; then
232 echo "$0: Unable to set to number of threads" >&2
233 exit 1
234 fi
235}
236
237config_get_modprobe_limit()
238{
239 if [[ -f ${MODPROBE_LIMIT_FILE} ]] ; then
240 MODPROBE_LIMIT=$(cat $MODPROBE_LIMIT_FILE)
241 fi
242 echo $MODPROBE_LIMIT
243}
244
245config_num_thread_limit_extra()
246{
247 MODPROBE_LIMIT=$(config_get_modprobe_limit)
248 let EXTRA_LIMIT=$MODPROBE_LIMIT+$1
249 config_num_threads $EXTRA_LIMIT
250}
251
252# For special characters use printf directly,
253# refer to kmod_test_0001
254config_set_driver()
255{
256 if ! echo -n $1 >$DIR/config_test_driver; then
257 echo "$0: Unable to set driver" >&2
258 exit 1
259 fi
260}
261
262config_set_fs()
263{
264 if ! echo -n $1 >$DIR/config_test_fs; then
265 echo "$0: Unable to set driver" >&2
266 exit 1
267 fi
268}
269
270config_get_driver()
271{
272 cat $DIR/config_test_driver
273}
274
275config_get_test_result()
276{
277 cat $DIR/test_result
278}
279
280config_reset()
281{
282 if ! echo -n "1" >"$DIR"/reset; then
283 echo "$0: reset shuld have worked" >&2
284 exit 1
285 fi
286}
287
288config_show_config()
289{
290 echo "----------------------------------------------------"
291 cat "$DIR"/config
292 echo "----------------------------------------------------"
293}
294
295config_trigger()
296{
297 if ! echo -n "1" >"$DIR"/trigger_config 2>/dev/null; then
298 echo "$1: FAIL - loading should have worked"
299 config_show_config
300 exit 1
301 fi
302 echo "$1: OK! - loading kmod test"
303}
304
305config_trigger_want_fail()
306{
307 if echo "1" > $DIR/trigger_config 2>/dev/null; then
308 echo "$1: FAIL - test case was expected to fail"
309 config_show_config
310 exit 1
311 fi
312 echo "$1: OK! - kmod test case failed as expected"
313}
314
315config_expect_result()
316{
317 RC=$(config_get_test_result)
318 RC_NAME=$(errno_val_to_name $RC)
319
320 ERRNO_NAME=$2
321 ERRNO=$(errno_name_to_val $ERRNO_NAME)
322
323 if [[ $ERRNO_NAME = "-ERR_ANY" ]]; then
324 if [[ $RC -ge 0 ]]; then
325 echo "$1: FAIL, test expects $ERRNO_NAME - got $RC_NAME ($RC)" >&2
326 config_show_config
327 exit 1
328 fi
329 elif [[ $RC != $ERRNO ]]; then
330 echo "$1: FAIL, test expects $ERRNO_NAME ($ERRNO) - got $RC_NAME ($RC)" >&2
331 config_show_config
332 exit 1
333 fi
334 echo "$1: OK! - Return value: $RC ($RC_NAME), expected $ERRNO_NAME"
335}
336
337kmod_defaults_driver()
338{
339 config_reset
340 modprobe -r $DEFAULT_KMOD_DRIVER
341 config_set_driver $DEFAULT_KMOD_DRIVER
342}
343
344kmod_defaults_fs()
345{
346 config_reset
347 modprobe -r $DEFAULT_KMOD_FS
348 config_set_fs $DEFAULT_KMOD_FS
349 config_set_test_case_fs
350}
351
352kmod_test_0001_driver()
353{
354 NAME='\000'
355
356 kmod_defaults_driver
357 config_num_threads 1
358 printf '\000' >"$DIR"/config_test_driver
359 config_trigger ${FUNCNAME[0]}
360 config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
361}
362
363kmod_test_0001_fs()
364{
365 NAME='\000'
366
367 kmod_defaults_fs
368 config_num_threads 1
369 printf '\000' >"$DIR"/config_test_fs
370 config_trigger ${FUNCNAME[0]}
371 config_expect_result ${FUNCNAME[0]} -EINVAL
372}
373
374kmod_test_0001()
375{
376 kmod_test_0001_driver
377 kmod_test_0001_fs
378}
379
380kmod_test_0002_driver()
381{
382 NAME="nope-$DEFAULT_KMOD_DRIVER"
383
384 kmod_defaults_driver
385 config_set_driver $NAME
386 config_num_threads 1
387 config_trigger ${FUNCNAME[0]}
388 config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
389}
390
391kmod_test_0002_fs()
392{
393 NAME="nope-$DEFAULT_KMOD_FS"
394
395 kmod_defaults_fs
396 config_set_fs $NAME
397 config_trigger ${FUNCNAME[0]}
398 config_expect_result ${FUNCNAME[0]} -EINVAL
399}
400
401kmod_test_0002()
402{
403 kmod_test_0002_driver
404 kmod_test_0002_fs
405}
406
407kmod_test_0003()
408{
409 kmod_defaults_fs
410 config_num_threads 1
411 config_trigger ${FUNCNAME[0]}
412 config_expect_result ${FUNCNAME[0]} SUCCESS
413}
414
415kmod_test_0004()
416{
417 kmod_defaults_fs
418 config_num_threads 2
419 config_trigger ${FUNCNAME[0]}
420 config_expect_result ${FUNCNAME[0]} SUCCESS
421}
422
423kmod_test_0005()
424{
425 kmod_defaults_driver
426 config_trigger ${FUNCNAME[0]}
427 config_expect_result ${FUNCNAME[0]} SUCCESS
428}
429
430kmod_test_0006()
431{
432 kmod_defaults_fs
433 config_trigger ${FUNCNAME[0]}
434 config_expect_result ${FUNCNAME[0]} SUCCESS
435}
436
437kmod_test_0007()
438{
439 kmod_test_0005
440 kmod_test_0006
441}
442
443kmod_test_0008()
444{
445 kmod_defaults_driver
446 MODPROBE_LIMIT=$(config_get_modprobe_limit)
447 let EXTRA=$MODPROBE_LIMIT/6
448 config_num_thread_limit_extra $EXTRA
449 config_trigger ${FUNCNAME[0]}
450 config_expect_result ${FUNCNAME[0]} SUCCESS
451}
452
453kmod_test_0009()
454{
455 kmod_defaults_fs
456 MODPROBE_LIMIT=$(config_get_modprobe_limit)
457 let EXTRA=$MODPROBE_LIMIT/4
458 config_num_thread_limit_extra $EXTRA
459 config_trigger ${FUNCNAME[0]}
460 config_expect_result ${FUNCNAME[0]} SUCCESS
461}
462
463list_tests()
464{
465 echo "Test ID list:"
466 echo
467 echo "TEST_ID x NUM_TEST"
468 echo "TEST_ID: Test ID"
469 echo "NUM_TESTS: Number of recommended times to run the test"
470 echo
471 echo "0001 x $(get_test_count 0001) - Simple test - 1 thread for empty string"
472 echo "0002 x $(get_test_count 0002) - Simple test - 1 thread for modules/filesystems that do not exist"
473 echo "0003 x $(get_test_count 0003) - Simple test - 1 thread for get_fs_type() only"
474 echo "0004 x $(get_test_count 0004) - Simple test - 2 threads for get_fs_type() only"
475 echo "0005 x $(get_test_count 0005) - multithreaded tests with default setup - request_module() only"
476 echo "0006 x $(get_test_count 0006) - multithreaded tests with default setup - get_fs_type() only"
477 echo "0007 x $(get_test_count 0007) - multithreaded tests with default setup test request_module() and get_fs_type()"
478 echo "0008 x $(get_test_count 0008) - multithreaded - push kmod_concurrent over max_modprobes for request_module()"
479 echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
480}
481
482usage()
483{
484 NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
485 let NUM_TESTS=$NUM_TESTS+1
486 MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
487 echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
488 echo " [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
489 echo " [ all ] [ -h | --help ] [ -l ]"
490 echo ""
491 echo "Valid tests: 0001-$MAX_TEST"
492 echo ""
493 echo " all Runs all tests (default)"
494 echo " -t Run test ID the number amount of times is recommended"
495 echo " -w Watch test ID run until it runs into an error"
496 echo " -c Run test ID once"
497 echo " -s Run test ID x test-count number of times"
498 echo " -l List all test ID list"
499 echo " -h|--help Help"
500 echo
501 echo "If an error every occurs execution will immediately terminate."
502 echo "If you are adding a new test try using -w <test-ID> first to"
503 echo "make sure the test passes a series of tests."
504 echo
505 echo Example uses:
506 echo
507 echo "${TEST_NAME}.sh -- executes all tests"
508 echo "${TEST_NAME}.sh -t 0008 -- Executes test ID 0008 number of times is recomended"
509 echo "${TEST_NAME}.sh -w 0008 -- Watch test ID 0008 run until an error occurs"
510 echo "${TEST_NAME}.sh -s 0008 -- Run test ID 0008 once"
511 echo "${TEST_NAME}.sh -c 0008 3 -- Run test ID 0008 three times"
512 echo
513 list_tests
514 exit 1
515}
516
517function test_num()
518{
519 re='^[0-9]+$'
520 if ! [[ $1 =~ $re ]]; then
521 usage
522 fi
523}
524
525function get_test_count()
526{
527 test_num $1
528 TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
529 LAST_TWO=${TEST_DATA#*:*}
530 echo ${LAST_TWO%:*}
531}
532
533function get_test_enabled()
534{
535 test_num $1
536 TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
537 echo ${TEST_DATA#*:*:}
538}
539
540function run_all_tests()
541{
542 for i in $ALL_TESTS ; do
543 TEST_ID=${i%:*:*}
544 ENABLED=$(get_test_enabled $TEST_ID)
545 TEST_COUNT=$(get_test_count $TEST_ID)
546 if [[ $ENABLED -eq "1" ]]; then
547 test_case $TEST_ID $TEST_COUNT
548 fi
549 done
550}
551
552function watch_log()
553{
554 if [ $# -ne 3 ]; then
555 clear
556 fi
557 date
558 echo "Running test: $2 - run #$1"
559}
560
561function watch_case()
562{
563 i=0
564 while [ 1 ]; do
565
566 if [ $# -eq 1 ]; then
567 test_num $1
568 watch_log $i ${TEST_NAME}_test_$1
569 ${TEST_NAME}_test_$1
570 else
571 watch_log $i all
572 run_all_tests
573 fi
574 let i=$i+1
575 done
576}
577
578function test_case()
579{
580 NUM_TESTS=$DEFAULT_NUM_TESTS
581 if [ $# -eq 2 ]; then
582 NUM_TESTS=$2
583 fi
584
585 i=0
586 while [ $i -lt $NUM_TESTS ]; do
587 test_num $1
588 watch_log $i ${TEST_NAME}_test_$1 noclear
589 RUN_TEST=${TEST_NAME}_test_$1
590 $RUN_TEST
591 let i=$i+1
592 done
593}
594
595function parse_args()
596{
597 if [ $# -eq 0 ]; then
598 run_all_tests
599 else
600 if [[ "$1" = "all" ]]; then
601 run_all_tests
602 elif [[ "$1" = "-w" ]]; then
603 shift
604 watch_case $@
605 elif [[ "$1" = "-t" ]]; then
606 shift
607 test_num $1
608 test_case $1 $(get_test_count $1)
609 elif [[ "$1" = "-c" ]]; then
610 shift
611 test_num $1
612 test_num $2
613 test_case $1 $2
614 elif [[ "$1" = "-s" ]]; then
615 shift
616 test_case $1 1
617 elif [[ "$1" = "-l" ]]; then
618 list_tests
619 elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
620 usage
621 else
622 usage
623 fi
624 fi
625}
626
627test_reqs
628allow_user_defaults
629load_req_mod
630
631trap "test_finish" EXIT
632
633parse_args $@
634
635exit 0