#!/bin/bash # # Test wrapper run inside the VM set -o nounset set -o errexit set -o errtrace export PS4='+`basename ${BASH_SOURCE[0]}`:${LINENO}:${FUNCNAME[0]:+${FUNCNAME[0]}()}+ ' KERNEL_ARCH="" . /host/$ktest_env ktest_dir="/host/$ktest_dir" ktest_tmp="/host/$ktest_tmp" if [ ! -e "/ktest" ]; then ln -s $ktest_dir /ktest fi . "$ktest_dir/lib/util.sh" . "$ktest_dir/lib/parse-test.sh" ktest_no_cleanup_tmpdir=1 ln -sf "/host/$ktest_kernel_binary/lib/modules" /lib/modules depmod -a mkdir -p /root/.ssh cat /host/$home/.ssh/id*.pub > /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys dmesg --console-on dmesg --console-level 8 echo 1 > /proc/sys/kernel/sysrq ulimit -c unlimited # Log file system visible to host LOGDIR=/ktest-out if [ ! -e "$LOGDIR" ]; then ln -s "/host/$ktest_out" $LOGDIR fi # Core dump settings echo 1 > /proc/sys/fs/suid_dumpable echo "|/bin/cp --sparse=always /dev/stdin $LOGDIR/core.%e.PID%p.SIG%s.TIME%t" > /proc/sys/kernel/core_pattern ulimit -c unlimited rm -f /ktest-out/core.* # Virtual block device tweaks echo none | tee /sys/block/sd*/queue/scheduler >/dev/null 2>&1 || true # Check if we are running the crashdump kernel if [[ -s /proc/vmcore ]]; then echo "Collecting crash dump..." rm -f "$LOGDIR/vmcore" cp --sparse=always /proc/vmcore "$LOGDIR/vmcore" || true sync poweroff fi # If debugging crash dumps, add "console=hvc0" to the append line # below: if [[ $ktest_crashdump = 1 ]]; then kexec -p /host/$ktest_kernel_binary/vmlinuz --append="root=/dev/sda rw maxcpus=1" || true fi NR_REBOOTS=0 EXPECTED_REBOOT=0 [[ -e /NR_REBOOTS ]] && NR_REBOOTS=$( /dev/null if compgen -G "$ktest_tmp/*.deb" > /dev/null; then if ! output=$(dpkg -i $ktest_tmp/*.deb); then echo $output exit 1 fi fi for i in "${ktest_make_install[@]}"; do pushd "/host/$i" > /dev/null if [[ -f autogen.sh && ! -f configure ]]; then run_quiet "autogen $(basename $i)" ./autogen.sh fi if [[ -f configure && ! -f Makefile ]]; then run_quiet "configure $(basename $i)" ./configure fi run_quiet "building $(basename $i)" make -j $ktest_cpus run_quiet "installing $(basename $i)" make -j $ktest_cpus install popd > /dev/null done get_stratch_devs() { echo sfdisk -X gpt /dev/sdb } copy_to_host() { cat /sys/kernel/debug/tracing/trace >> $LOGDIR/trace.txt # Code coverage gcov_dir=/sys/kernel/debug/gcov if [[ -d $gcov_dir ]]; then # find a destination dir that doesn't exist, so we can copy multiple # sets of gcov data from different tests/reboots and merge them later for i in {0..99}; do dst=$LOGDIR/gcov.$i if [[ ! -d $dst ]]; then cp -dR $gcov_dir $dst break fi done fi sync } check_taint() { read taint < /proc/sys/kernel/tainted if [[ $taint != 0 ]]; then echo "Failure because kernel tainted - check log for warnings" echo "TEST FAILED" exit 0 fi } do_reboot() { copy_to_host check_taint echo $((NR_REBOOTS + 1)) | dd of=/EXPECTED_REBOOT oflag=direct 2> /dev/null echo b > /proc/sysrq-trigger } for h in $(declare -F|sed -ne '/ hook_/ s/.*hook_// p'); do run_quiet "running test hook $h" hook_$h done echo -n "Kernel version: " uname -r if [[ $(type -t list_tests) == function ]]; then tests=$(list_tests) else tests=$(declare -F|sed -ne '/ test_/ s/.*test_// p') fi # may be overridden by test: if [[ $(type -t run_test) != function ]]; then run_test() { local test=test_$1 if [[ $(type -t $test) != function ]]; then echo "test $1 does not exist" exit 1 fi $test } fi # may be overridden by test: if [[ $(type -t run_tests) != function ]]; then run_tests() { local tests_passed=() local tests_failed=() echo echo "Running tests $@" echo for i in $@; do echo "========= TEST $i" echo local start=$(date '+%s') local ret=0 (set -e; run_test $i) ret=$? local finish=$(date '+%s') pkill -P $$ >/dev/null # XXX: check dmesg for warnings, oopses, slab corruption, etc. before # signaling success echo if [[ $ret = 0 ]]; then echo "========= PASSED $i in $(($finish - $start))s" tests_passed+=($i) else echo "========= FAILED $i in $(($finish - $start))s" tests_failed+=($i) # Try to clean up after a failed test so we can run the rest of # the tests - unless failfast is enabled, or there was only one # test to run: [[ $ktest_failfast = 1 ]] && break [[ $# = 1 ]] && break for mnt in $(awk '{print $2}' /proc/mounts|grep ^/mnt|sort -r); do while [[ -n $(fuser -k -M -m $mnt) ]]; do sleep 1 done umount $mnt done fi done echo echo "Passed: ${tests_passed[@]}" echo "Failed: ${tests_failed[@]}" return ${#tests_failed[@]} } fi if [[ -z $tests ]]; then echo "No tests found" echo "TEST FAILED" exit 1 fi [[ -n $ktest_testargs ]] && tests="$ktest_testargs" tests=$(echo $tests) if [[ $tests = "none" ]]; then echo "No tests to run" echo "TEST FAILED" exit 0 fi if [[ $ktest_exit_on_success = 0 && $ktest_interactive = 0 ]]; then ( sleep $ktest_timeout echo "TEST TIMEOUT - triggering crash" echo c > /proc/sysrq-trigger ) & fi trap 'pkill -P $$ >/dev/null' EXIT cd /root set +e ret=0 while [[ $ret = 0 ]]; do run_tests $tests ret=$? pkill -P $$ >/dev/null || true [[ $ret != 0 ]] && break [[ $ktest_loop = 1 ]] || break done copy_to_host check_taint echo -n "Kernel version: " uname -r if [[ $ret = 0 ]]; then echo "TEST SUCCESS" else echo "TEST FAILED" fi exit 0