Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/hid: update vmtest.sh for virtme-ng

This commit is a rewrite almost from scratch of vmtest.sh.

By relying on virtme-ng, we get rid of boot2container, reducing the
total bootup time (and network requirements). That means that we are
relying on the programs being installed on the host, but that shouldn't
be an issue. The generation of the kconfig is also now handled by
virtme-ng, so that's one less thing to worry.

I used tools/testing/selftests/vsock/vmtest.sh as a base and modified it
to look mostly like my previous script:
- removed the custom ssh handling
- make use of vng for compiling, which allows to bring remote
compilation (and potentially remote compilation on a remote container)
- change the verbosity logic by having 2 levels:
- first one shows the tests outputs
- second level also shows the VM logs
- instead of only running the compiled kernel when it is built, if we
are in the kernel tree, use the kernel artifacts there (and complain
if they are not built)
- adapted the tests list to match the HID subsystem tests

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
be66a27b 02d6eeed

+446 -268
+446 -268
tools/testing/selftests/hid/vmtest.sh
··· 1 1 #!/bin/bash 2 2 # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Copyright (c) 2025 Red Hat 5 + # Copyright (c) 2025 Meta Platforms, Inc. and affiliates 6 + # 7 + # Dependencies: 8 + # * virtme-ng 9 + # * busybox-static (used by virtme-ng) 10 + # * qemu (used by virtme-ng) 3 11 4 - set -u 5 - set -e 12 + readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" 13 + readonly KERNEL_CHECKOUT=$(realpath "${SCRIPT_DIR}"/../../../../) 6 14 7 - # This script currently only works for x86_64 8 - ARCH="$(uname -m)" 9 - case "${ARCH}" in 10 - x86_64) 11 - QEMU_BINARY=qemu-system-x86_64 12 - BZIMAGE="arch/x86/boot/bzImage" 13 - ;; 14 - *) 15 - echo "Unsupported architecture" 16 - exit 1 17 - ;; 18 - esac 19 - SCRIPT_DIR="$(dirname $(realpath $0))" 20 - OUTPUT_DIR="$SCRIPT_DIR/results" 21 - KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}") 22 - B2C_URL="https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/main/vm2c.py" 23 - NUM_COMPILE_JOBS="$(nproc)" 24 - LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")" 25 - LOG_FILE="${LOG_FILE_BASE}.log" 26 - EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status" 27 - CONTAINER_IMAGE="registry.freedesktop.org/bentiss/hid/fedora/39:2023-11-22.1" 15 + source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh 28 16 29 - TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}" 30 - DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests" 17 + readonly HID_BPF_TEST="${SCRIPT_DIR}"/hid_bpf 18 + readonly HIDRAW_TEST="${SCRIPT_DIR}"/hidraw 19 + readonly HID_BPF_PROGS="${KERNEL_CHECKOUT}/drivers/hid/bpf/progs" 20 + readonly SSH_GUEST_PORT=22 21 + readonly WAIT_PERIOD=3 22 + readonly WAIT_PERIOD_MAX=60 23 + readonly WAIT_TOTAL=$(( WAIT_PERIOD * WAIT_PERIOD_MAX )) 24 + readonly QEMU_PIDFILE=$(mktemp /tmp/qemu_hid_vmtest_XXXX.pid) 31 25 32 - usage() 33 - { 34 - cat <<EOF 35 - Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] -- [<command>] 26 + readonly QEMU_OPTS="\ 27 + --pidfile ${QEMU_PIDFILE} \ 28 + " 29 + readonly KERNEL_CMDLINE="" 30 + readonly LOG=$(mktemp /tmp/hid_vmtest_XXXX.log) 31 + readonly TEST_NAMES=(vm_hid_bpf vm_hidraw vm_pytest) 32 + readonly TEST_DESCS=( 33 + "Run hid_bpf tests in the VM." 34 + "Run hidraw tests in the VM." 35 + "Run the hid-tools test-suite in the VM." 36 + ) 36 37 37 - <command> is the command you would normally run when you are in 38 - the source kernel direcory. e.g: 38 + VERBOSE=0 39 + SHELL_MODE=0 40 + BUILD_HOST="" 41 + BUILD_HOST_PODMAN_CONTAINER_NAME="" 39 42 40 - $0 -- ./tools/testing/selftests/hid/hid_bpf 43 + usage() { 44 + local name 45 + local desc 46 + local i 41 47 42 - If no command is specified and a debug shell (-s) is not requested, 43 - "${DEFAULT_COMMAND}" will be run by default. 48 + echo 49 + echo "$0 [OPTIONS] [TEST]... [-- tests-args]" 50 + echo "If no TEST argument is given, all tests will be run." 51 + echo 52 + echo "Options" 53 + echo " -b: build the kernel from the current source tree and use it for guest VMs" 54 + echo " -H: hostname for remote build host (used with -b)" 55 + echo " -p: podman container name for remote build host (used with -b)" 56 + echo " Example: -H beefyserver -p vng" 57 + echo " -q: set the path to or name of qemu binary" 58 + echo " -s: start a shell in the VM instead of running tests" 59 + echo " -v: more verbose output (can be repeated multiple times)" 60 + echo 61 + echo "Available tests" 44 62 45 - If you build your kernel using KBUILD_OUTPUT= or O= options, these 46 - can be passed as environment variables to the script: 47 - 48 - O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 49 - 50 - or 51 - 52 - KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 53 - 54 - Options: 55 - 56 - -u) Update the boot2container script to a newer version. 57 - -d) Update the output directory (default: ${OUTPUT_DIR}) 58 - -b) Run only the build steps for the kernel and the selftests 59 - -j) Number of jobs for compilation, similar to -j in make 60 - (default: ${NUM_COMPILE_JOBS}) 61 - -s) Instead of powering off the VM, start an interactive 62 - shell. If <command> is specified, the shell runs after 63 - the command finishes executing 64 - EOF 65 - } 66 - 67 - download() 68 - { 69 - local file="$1" 70 - 71 - echo "Downloading $file..." >&2 72 - curl -Lsf "$file" -o "${@:2}" 73 - } 74 - 75 - recompile_kernel() 76 - { 77 - local kernel_checkout="$1" 78 - local make_command="$2" 79 - 80 - cd "${kernel_checkout}" 81 - 82 - ${make_command} olddefconfig 83 - ${make_command} headers 84 - ${make_command} 85 - } 86 - 87 - update_selftests() 88 - { 89 - local kernel_checkout="$1" 90 - local selftests_dir="${kernel_checkout}/tools/testing/selftests/hid" 91 - 92 - cd "${selftests_dir}" 93 - ${make_command} 94 - } 95 - 96 - run_vm() 97 - { 98 - local run_dir="$1" 99 - local b2c="$2" 100 - local kernel_bzimage="$3" 101 - local command="$4" 102 - local post_command="" 103 - 104 - cd "${run_dir}" 105 - 106 - if ! which "${QEMU_BINARY}" &> /dev/null; then 107 - cat <<EOF 108 - Could not find ${QEMU_BINARY} 109 - Please install qemu or set the QEMU_BINARY environment variable. 110 - EOF 111 - exit 1 112 - fi 113 - 114 - # alpine (used in post-container requires the PATH to have /bin 115 - export PATH=$PATH:/bin 116 - 117 - if [[ "${debug_shell}" != "yes" ]] 118 - then 119 - touch ${OUTPUT_DIR}/${LOG_FILE} 120 - command="mount bpffs -t bpf /sys/fs/bpf/; set -o pipefail ; ${command} 2>&1 | tee ${OUTPUT_DIR}/${LOG_FILE}" 121 - post_command="cat ${OUTPUT_DIR}/${LOG_FILE}" 122 - else 123 - command="mount bpffs -t bpf /sys/fs/bpf/; ${command}" 124 - fi 125 - 126 - set +e 127 - $b2c --command "${command}" \ 128 - --kernel ${kernel_bzimage} \ 129 - --workdir ${OUTPUT_DIR} \ 130 - --image ${CONTAINER_IMAGE} 131 - 132 - echo $? > ${OUTPUT_DIR}/${EXIT_STATUS_FILE} 133 - 134 - set -e 135 - 136 - ${post_command} 137 - } 138 - 139 - is_rel_path() 140 - { 141 - local path="$1" 142 - 143 - [[ ${path:0:1} != "/" ]] 144 - } 145 - 146 - do_update_kconfig() 147 - { 148 - local kernel_checkout="$1" 149 - local kconfig_file="$2" 150 - 151 - rm -f "$kconfig_file" 2> /dev/null 152 - 153 - for config in "${KCONFIG_REL_PATHS[@]}"; do 154 - local kconfig_src="${config}" 155 - cat "$kconfig_src" >> "$kconfig_file" 63 + for ((i = 0; i < ${#TEST_NAMES[@]}; i++)); do 64 + name=${TEST_NAMES[${i}]} 65 + desc=${TEST_DESCS[${i}]} 66 + printf "\t%-35s%-35s\n" "${name}" "${desc}" 156 67 done 68 + echo 69 + 70 + exit 1 157 71 } 158 72 159 - update_kconfig() 160 - { 161 - local kernel_checkout="$1" 162 - local kconfig_file="$2" 73 + die() { 74 + echo "$*" >&2 75 + exit "${KSFT_FAIL}" 76 + } 163 77 164 - if [[ -f "${kconfig_file}" ]]; then 165 - local local_modified="$(stat -c %Y "${kconfig_file}")" 78 + vm_ssh() { 79 + # vng --ssh-client keeps shouting "Warning: Permanently added 'virtme-ng%22' 80 + # (ED25519) to the list of known hosts.", 81 + # So replace the command with what's actually called and add the "-q" option 82 + stdbuf -oL ssh -q \ 83 + -F ${HOME}/.cache/virtme-ng/.ssh/virtme-ng-ssh.conf \ 84 + -l root virtme-ng%${SSH_GUEST_PORT} \ 85 + "$@" 86 + return $? 87 + } 166 88 167 - for config in "${KCONFIG_REL_PATHS[@]}"; do 168 - local kconfig_src="${config}" 169 - local src_modified="$(stat -c %Y "${kconfig_src}")" 170 - # Only update the config if it has been updated after the 171 - # previously cached config was created. This avoids 172 - # unnecessarily compiling the kernel and selftests. 173 - if [[ "${src_modified}" -gt "${local_modified}" ]]; then 174 - do_update_kconfig "$kernel_checkout" "$kconfig_file" 175 - # Once we have found one outdated configuration 176 - # there is no need to check other ones. 89 + cleanup() { 90 + if [[ -s "${QEMU_PIDFILE}" ]]; then 91 + pkill -SIGTERM -F "${QEMU_PIDFILE}" > /dev/null 2>&1 92 + fi 93 + 94 + # If failure occurred during or before qemu start up, then we need 95 + # to clean this up ourselves. 96 + if [[ -e "${QEMU_PIDFILE}" ]]; then 97 + rm "${QEMU_PIDFILE}" 98 + fi 99 + } 100 + 101 + check_args() { 102 + local found 103 + 104 + for arg in "$@"; do 105 + found=0 106 + for name in "${TEST_NAMES[@]}"; do 107 + if [[ "${name}" = "${arg}" ]]; then 108 + found=1 177 109 break 178 110 fi 179 111 done 180 - else 181 - do_update_kconfig "$kernel_checkout" "$kconfig_file" 182 - fi 183 - } 184 112 185 - main() 186 - { 187 - local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" 188 - local kernel_checkout=$(realpath "${script_dir}"/../../../../) 189 - # By default the script searches for the kernel in the checkout directory but 190 - # it also obeys environment variables O= and KBUILD_OUTPUT= 191 - local kernel_bzimage="${kernel_checkout}/${BZIMAGE}" 192 - local command="${DEFAULT_COMMAND}" 193 - local update_b2c="no" 194 - local debug_shell="no" 195 - local build_only="no" 196 - 197 - while getopts ':hsud:j:b' opt; do 198 - case ${opt} in 199 - u) 200 - update_b2c="yes" 201 - ;; 202 - d) 203 - OUTPUT_DIR="$OPTARG" 204 - ;; 205 - j) 206 - NUM_COMPILE_JOBS="$OPTARG" 207 - ;; 208 - s) 209 - command="/bin/sh" 210 - debug_shell="yes" 211 - ;; 212 - b) 213 - build_only="yes" 214 - ;; 215 - h) 113 + if [[ "${found}" -eq 0 ]]; then 114 + echo "${arg} is not an available test" >&2 216 115 usage 217 - exit 0 218 - ;; 219 - \? ) 220 - echo "Invalid Option: -$OPTARG" 221 - usage 222 - exit 1 223 - ;; 224 - : ) 225 - echo "Invalid Option: -$OPTARG requires an argument" 226 - usage 227 - exit 1 228 - ;; 229 - esac 116 + fi 230 117 done 231 - shift $((OPTIND -1)) 232 118 233 - # trap 'catch "$?"' EXIT 234 - if [[ "${build_only}" == "no" && "${debug_shell}" == "no" ]]; then 235 - if [[ $# -eq 0 ]]; then 236 - echo "No command specified, will run ${DEFAULT_COMMAND} in the vm" 237 - else 238 - command="$@" 239 - 240 - if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]] 241 - then 242 - debug_shell="yes" 243 - fi 119 + for arg in "$@"; do 120 + if ! command -v > /dev/null "test_${arg}"; then 121 + echo "Test ${arg} not found" >&2 122 + usage 244 123 fi 124 + done 125 + } 126 + 127 + check_deps() { 128 + for dep in vng ${QEMU} busybox pkill ssh pytest; do 129 + if [[ ! -x $(command -v "${dep}") ]]; then 130 + echo -e "skip: dependency ${dep} not found!\n" 131 + exit "${KSFT_SKIP}" 132 + fi 133 + done 134 + 135 + if [[ ! -x $(command -v "${HID_BPF_TEST}") ]]; then 136 + printf "skip: %s not found!" "${HID_BPF_TEST}" 137 + printf " Please build the kselftest hid_bpf target.\n" 138 + exit "${KSFT_SKIP}" 245 139 fi 246 140 247 - local kconfig_file="${OUTPUT_DIR}/latest.config" 248 - local make_command="make -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}" 249 - 250 - # Figure out where the kernel is being built. 251 - # O takes precedence over KBUILD_OUTPUT. 252 - if [[ "${O:=""}" != "" ]]; then 253 - if is_rel_path "${O}"; then 254 - O="$(realpath "${PWD}/${O}")" 255 - fi 256 - kernel_bzimage="${O}/${BZIMAGE}" 257 - make_command="${make_command} O=${O}" 258 - elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then 259 - if is_rel_path "${KBUILD_OUTPUT}"; then 260 - KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")" 261 - fi 262 - kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}" 263 - make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}" 264 - fi 265 - 266 - local b2c="${OUTPUT_DIR}/vm2c.py" 267 - 268 - echo "Output directory: ${OUTPUT_DIR}" 269 - 270 - mkdir -p "${OUTPUT_DIR}" 271 - update_kconfig "${kernel_checkout}" "${kconfig_file}" 272 - 273 - recompile_kernel "${kernel_checkout}" "${make_command}" 274 - update_selftests "${kernel_checkout}" "${make_command}" 275 - 276 - if [[ "${build_only}" == "no" ]]; then 277 - if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then 278 - echo "vm2c script not found in ${b2c}" 279 - update_b2c="yes" 280 - fi 281 - 282 - if [[ "${update_b2c}" == "yes" ]]; then 283 - download $B2C_URL $b2c 284 - chmod +x $b2c 285 - fi 286 - 287 - run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}" 288 - if [[ "${debug_shell}" != "yes" ]]; then 289 - echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}" 290 - fi 291 - 292 - exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE}) 141 + if [[ ! -x $(command -v "${HIDRAW_TEST}") ]]; then 142 + printf "skip: %s not found!" "${HIDRAW_TEST}" 143 + printf " Please build the kselftest hidraw target.\n" 144 + exit "${KSFT_SKIP}" 293 145 fi 294 146 } 295 147 296 - main "$@" 148 + check_vng() { 149 + local tested_versions 150 + local version 151 + local ok 152 + 153 + tested_versions=("1.36" "1.37") 154 + version="$(vng --version)" 155 + 156 + ok=0 157 + for tv in "${tested_versions[@]}"; do 158 + if [[ "${version}" == *"${tv}"* ]]; then 159 + ok=1 160 + break 161 + fi 162 + done 163 + 164 + if [[ ! "${ok}" -eq 1 ]]; then 165 + printf "warning: vng version '%s' has not been tested and may " "${version}" >&2 166 + printf "not function properly.\n\tThe following versions have been tested: " >&2 167 + echo "${tested_versions[@]}" >&2 168 + fi 169 + } 170 + 171 + handle_build() { 172 + if [[ ! "${BUILD}" -eq 1 ]]; then 173 + return 174 + fi 175 + 176 + if [[ ! -d "${KERNEL_CHECKOUT}" ]]; then 177 + echo "-b requires vmtest.sh called from the kernel source tree" >&2 178 + exit 1 179 + fi 180 + 181 + pushd "${KERNEL_CHECKOUT}" &>/dev/null 182 + 183 + if ! vng --kconfig --config "${SCRIPT_DIR}"/config; then 184 + die "failed to generate .config for kernel source tree (${KERNEL_CHECKOUT})" 185 + fi 186 + 187 + local vng_args=("-v" "--config" "${SCRIPT_DIR}/config" "--build") 188 + 189 + if [[ -n "${BUILD_HOST}" ]]; then 190 + vng_args+=("--build-host" "${BUILD_HOST}") 191 + fi 192 + 193 + if [[ -n "${BUILD_HOST_PODMAN_CONTAINER_NAME}" ]]; then 194 + vng_args+=("--build-host-exec-prefix" \ 195 + "podman exec -ti ${BUILD_HOST_PODMAN_CONTAINER_NAME}") 196 + fi 197 + 198 + if ! vng "${vng_args[@]}"; then 199 + die "failed to build kernel from source tree (${KERNEL_CHECKOUT})" 200 + fi 201 + 202 + if ! make -j$(nproc) -C "${HID_BPF_PROGS}"; then 203 + die "failed to build HID bpf objects from source tree (${HID_BPF_PROGS})" 204 + fi 205 + 206 + if ! make -j$(nproc) -C "${SCRIPT_DIR}"; then 207 + die "failed to build HID selftests from source tree (${SCRIPT_DIR})" 208 + fi 209 + 210 + popd &>/dev/null 211 + } 212 + 213 + vm_start() { 214 + local logfile=/dev/null 215 + local verbose_opt="" 216 + local kernel_opt="" 217 + local qemu 218 + 219 + qemu=$(command -v "${QEMU}") 220 + 221 + if [[ "${VERBOSE}" -eq 2 ]]; then 222 + verbose_opt="--verbose" 223 + logfile=/dev/stdout 224 + fi 225 + 226 + # If we are running from within the kernel source tree, use the kernel source tree 227 + # as the kernel to boot, otherwise use the currently running kernel. 228 + if [[ "$(realpath "$(pwd)")" == "${KERNEL_CHECKOUT}"* ]]; then 229 + kernel_opt="${KERNEL_CHECKOUT}" 230 + fi 231 + 232 + vng \ 233 + --run \ 234 + ${kernel_opt} \ 235 + ${verbose_opt} \ 236 + --qemu-opts="${QEMU_OPTS}" \ 237 + --qemu="${qemu}" \ 238 + --user root \ 239 + --append "${KERNEL_CMDLINE}" \ 240 + --ssh "${SSH_GUEST_PORT}" \ 241 + --rw &> ${logfile} & 242 + 243 + local vng_pid=$! 244 + local elapsed=0 245 + 246 + while [[ ! -s "${QEMU_PIDFILE}" ]]; do 247 + if ! kill -0 "${vng_pid}" 2>/dev/null; then 248 + echo "vng process (PID ${vng_pid}) exited early, check logs for details" >&2 249 + die "failed to boot VM" 250 + fi 251 + 252 + if [[ ${elapsed} -ge ${WAIT_TOTAL} ]]; then 253 + echo "Timed out after ${WAIT_TOTAL} seconds waiting for VM to boot" >&2 254 + die "failed to boot VM" 255 + fi 256 + 257 + sleep 1 258 + elapsed=$((elapsed + 1)) 259 + done 260 + } 261 + 262 + vm_wait_for_ssh() { 263 + local i 264 + 265 + i=0 266 + while true; do 267 + if [[ ${i} -gt ${WAIT_PERIOD_MAX} ]]; then 268 + die "Timed out waiting for guest ssh" 269 + fi 270 + if vm_ssh -- true; then 271 + break 272 + fi 273 + i=$(( i + 1 )) 274 + sleep ${WAIT_PERIOD} 275 + done 276 + } 277 + 278 + vm_mount_bpffs() { 279 + vm_ssh -- mount bpffs -t bpf /sys/fs/bpf 280 + } 281 + 282 + __log_stdin() { 283 + stdbuf -oL awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0; fflush() }' 284 + } 285 + 286 + __log_args() { 287 + echo "$*" | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }' 288 + } 289 + 290 + log() { 291 + local verbose="$1" 292 + shift 293 + 294 + local prefix="$1" 295 + 296 + shift 297 + local redirect= 298 + if [[ ${verbose} -le 0 ]]; then 299 + redirect=/dev/null 300 + else 301 + redirect=/dev/stdout 302 + fi 303 + 304 + if [[ "$#" -eq 0 ]]; then 305 + __log_stdin | tee -a "${LOG}" > ${redirect} 306 + else 307 + __log_args "$@" | tee -a "${LOG}" > ${redirect} 308 + fi 309 + } 310 + 311 + log_setup() { 312 + log $((VERBOSE-1)) "setup" "$@" 313 + } 314 + 315 + log_host() { 316 + local testname=$1 317 + 318 + shift 319 + log $((VERBOSE-1)) "test:${testname}:host" "$@" 320 + } 321 + 322 + log_guest() { 323 + local testname=$1 324 + 325 + shift 326 + log ${VERBOSE} "# test:${testname}" "$@" 327 + } 328 + 329 + test_vm_hid_bpf() { 330 + local testname="${FUNCNAME[0]#test_}" 331 + 332 + vm_ssh -- "${HID_BPF_TEST}" \ 333 + 2>&1 | log_guest "${testname}" 334 + 335 + return ${PIPESTATUS[0]} 336 + } 337 + 338 + test_vm_hidraw() { 339 + local testname="${FUNCNAME[0]#test_}" 340 + 341 + vm_ssh -- "${HIDRAW_TEST}" \ 342 + 2>&1 | log_guest "${testname}" 343 + 344 + return ${PIPESTATUS[0]} 345 + } 346 + 347 + test_vm_pytest() { 348 + local testname="${FUNCNAME[0]#test_}" 349 + 350 + shift 351 + 352 + vm_ssh -- pytest ${SCRIPT_DIR}/tests --color=yes "$@" \ 353 + 2>&1 | log_guest "${testname}" 354 + 355 + return ${PIPESTATUS[0]} 356 + } 357 + 358 + run_test() { 359 + local vm_oops_cnt_before 360 + local vm_warn_cnt_before 361 + local vm_oops_cnt_after 362 + local vm_warn_cnt_after 363 + local name 364 + local rc 365 + 366 + vm_oops_cnt_before=$(vm_ssh -- dmesg | grep -c -i 'Oops') 367 + vm_error_cnt_before=$(vm_ssh -- dmesg --level=err | wc -l) 368 + 369 + name=$(echo "${1}" | awk '{ print $1 }') 370 + eval test_"${name}" "$@" 371 + rc=$? 372 + 373 + vm_oops_cnt_after=$(vm_ssh -- dmesg | grep -i 'Oops' | wc -l) 374 + if [[ ${vm_oops_cnt_after} -gt ${vm_oops_cnt_before} ]]; then 375 + echo "FAIL: kernel oops detected on vm" | log_host "${name}" 376 + rc=$KSFT_FAIL 377 + fi 378 + 379 + vm_error_cnt_after=$(vm_ssh -- dmesg --level=err | wc -l) 380 + if [[ ${vm_error_cnt_after} -gt ${vm_error_cnt_before} ]]; then 381 + echo "FAIL: kernel error detected on vm" | log_host "${name}" 382 + vm_ssh -- dmesg --level=err | log_host "${name}" 383 + rc=$KSFT_FAIL 384 + fi 385 + 386 + return "${rc}" 387 + } 388 + 389 + QEMU="qemu-system-$(uname -m)" 390 + 391 + while getopts :hvsbq:H:p: o 392 + do 393 + case $o in 394 + v) VERBOSE=$((VERBOSE+1));; 395 + s) SHELL_MODE=1;; 396 + b) BUILD=1;; 397 + q) QEMU=$OPTARG;; 398 + H) BUILD_HOST=$OPTARG;; 399 + p) BUILD_HOST_PODMAN_CONTAINER_NAME=$OPTARG;; 400 + h|*) usage;; 401 + esac 402 + done 403 + shift $((OPTIND-1)) 404 + 405 + trap cleanup EXIT 406 + 407 + PARAMS="" 408 + 409 + if [[ ${#} -eq 0 ]]; then 410 + ARGS=("${TEST_NAMES[@]}") 411 + else 412 + ARGS=() 413 + COUNT=0 414 + for arg in $@; do 415 + COUNT=$((COUNT+1)) 416 + if [[ x"$arg" == x"--" ]]; then 417 + break 418 + fi 419 + ARGS+=($arg) 420 + done 421 + shift $COUNT 422 + PARAMS="$@" 423 + fi 424 + 425 + if [[ "${SHELL_MODE}" -eq 0 ]]; then 426 + check_args "${ARGS[@]}" 427 + echo "1..${#ARGS[@]}" 428 + fi 429 + check_deps 430 + check_vng 431 + handle_build 432 + 433 + log_setup "Booting up VM" 434 + vm_start 435 + vm_wait_for_ssh 436 + vm_mount_bpffs 437 + log_setup "VM booted up" 438 + 439 + if [[ "${SHELL_MODE}" -eq 1 ]]; then 440 + log_setup "Starting interactive shell in VM" 441 + echo "Starting shell in VM. Use 'exit' to quit and shutdown the VM." 442 + CURRENT_DIR="$(pwd)" 443 + vm_ssh -t -- "cd '${CURRENT_DIR}' && exec bash -l" 444 + exit "$KSFT_PASS" 445 + fi 446 + 447 + cnt_pass=0 448 + cnt_fail=0 449 + cnt_skip=0 450 + cnt_total=0 451 + for arg in "${ARGS[@]}"; do 452 + run_test "${arg}" "${PARAMS}" 453 + rc=$? 454 + if [[ ${rc} -eq $KSFT_PASS ]]; then 455 + cnt_pass=$(( cnt_pass + 1 )) 456 + echo "ok ${cnt_total} ${arg}" 457 + elif [[ ${rc} -eq $KSFT_SKIP ]]; then 458 + cnt_skip=$(( cnt_skip + 1 )) 459 + echo "ok ${cnt_total} ${arg} # SKIP" 460 + elif [[ ${rc} -eq $KSFT_FAIL ]]; then 461 + cnt_fail=$(( cnt_fail + 1 )) 462 + echo "not ok ${cnt_total} ${arg} # exit=$rc" 463 + fi 464 + cnt_total=$(( cnt_total + 1 )) 465 + done 466 + 467 + echo "SUMMARY: PASS=${cnt_pass} SKIP=${cnt_skip} FAIL=${cnt_fail}" 468 + echo "Log: ${LOG}" 469 + 470 + if [ $((cnt_pass + cnt_skip)) -eq ${cnt_total} ]; then 471 + exit "$KSFT_PASS" 472 + else 473 + exit "$KSFT_FAIL" 474 + fi