···11#!/bin/bash22# SPDX-License-Identifier: GPL-2.033+#44+# Copyright (c) 2025 Red Hat55+# Copyright (c) 2025 Meta Platforms, Inc. and affiliates66+#77+# Dependencies:88+# * virtme-ng99+# * busybox-static (used by virtme-ng)1010+# * qemu (used by virtme-ng)31144-set -u55-set -e1212+readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"1313+readonly KERNEL_CHECKOUT=$(realpath "${SCRIPT_DIR}"/../../../../)61477-# This script currently only works for x86_6488-ARCH="$(uname -m)"99-case "${ARCH}" in1010-x86_64)1111- QEMU_BINARY=qemu-system-x86_641212- BZIMAGE="arch/x86/boot/bzImage"1313- ;;1414-*)1515- echo "Unsupported architecture"1616- exit 11717- ;;1818-esac1919-SCRIPT_DIR="$(dirname $(realpath $0))"2020-OUTPUT_DIR="$SCRIPT_DIR/results"2121-KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}")2222-B2C_URL="https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/main/vm2c.py"2323-NUM_COMPILE_JOBS="$(nproc)"2424-LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")"2525-LOG_FILE="${LOG_FILE_BASE}.log"2626-EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"2727-CONTAINER_IMAGE="registry.freedesktop.org/bentiss/hid/fedora/39:2023-11-22.1"1515+source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh28162929-TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}"3030-DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests"1717+readonly HID_BPF_TEST="${SCRIPT_DIR}"/hid_bpf1818+readonly HIDRAW_TEST="${SCRIPT_DIR}"/hidraw1919+readonly HID_BPF_PROGS="${KERNEL_CHECKOUT}/drivers/hid/bpf/progs"2020+readonly SSH_GUEST_PORT=222121+readonly WAIT_PERIOD=32222+readonly WAIT_PERIOD_MAX=602323+readonly WAIT_TOTAL=$(( WAIT_PERIOD * WAIT_PERIOD_MAX ))2424+readonly QEMU_PIDFILE=$(mktemp /tmp/qemu_hid_vmtest_XXXX.pid)31253232-usage()3333-{3434- cat <<EOF3535-Usage: $0 [-j N] [-s] [-b] [-d <output_dir>] -- [<command>]2626+readonly QEMU_OPTS="\2727+ --pidfile ${QEMU_PIDFILE} \2828+"2929+readonly KERNEL_CMDLINE=""3030+readonly LOG=$(mktemp /tmp/hid_vmtest_XXXX.log)3131+readonly TEST_NAMES=(vm_hid_bpf vm_hidraw vm_pytest)3232+readonly TEST_DESCS=(3333+ "Run hid_bpf tests in the VM."3434+ "Run hidraw tests in the VM."3535+ "Run the hid-tools test-suite in the VM."3636+)36373737-<command> is the command you would normally run when you are in3838-the source kernel direcory. e.g:3838+VERBOSE=03939+SHELL_MODE=04040+BUILD_HOST=""4141+BUILD_HOST_PODMAN_CONTAINER_NAME=""39424040- $0 -- ./tools/testing/selftests/hid/hid_bpf4343+usage() {4444+ local name4545+ local desc4646+ local i41474242-If no command is specified and a debug shell (-s) is not requested,4343-"${DEFAULT_COMMAND}" will be run by default.4848+ echo4949+ echo "$0 [OPTIONS] [TEST]... [-- tests-args]"5050+ echo "If no TEST argument is given, all tests will be run."5151+ echo5252+ echo "Options"5353+ echo " -b: build the kernel from the current source tree and use it for guest VMs"5454+ echo " -H: hostname for remote build host (used with -b)"5555+ echo " -p: podman container name for remote build host (used with -b)"5656+ echo " Example: -H beefyserver -p vng"5757+ echo " -q: set the path to or name of qemu binary"5858+ echo " -s: start a shell in the VM instead of running tests"5959+ echo " -v: more verbose output (can be repeated multiple times)"6060+ echo6161+ echo "Available tests"44624545-If you build your kernel using KBUILD_OUTPUT= or O= options, these4646-can be passed as environment variables to the script:4747-4848- O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf4949-5050-or5151-5252- KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf5353-5454-Options:5555-5656- -u) Update the boot2container script to a newer version.5757- -d) Update the output directory (default: ${OUTPUT_DIR})5858- -b) Run only the build steps for the kernel and the selftests5959- -j) Number of jobs for compilation, similar to -j in make6060- (default: ${NUM_COMPILE_JOBS})6161- -s) Instead of powering off the VM, start an interactive6262- shell. If <command> is specified, the shell runs after6363- the command finishes executing6464-EOF6565-}6666-6767-download()6868-{6969- local file="$1"7070-7171- echo "Downloading $file..." >&27272- curl -Lsf "$file" -o "${@:2}"7373-}7474-7575-recompile_kernel()7676-{7777- local kernel_checkout="$1"7878- local make_command="$2"7979-8080- cd "${kernel_checkout}"8181-8282- ${make_command} olddefconfig8383- ${make_command} headers8484- ${make_command}8585-}8686-8787-update_selftests()8888-{8989- local kernel_checkout="$1"9090- local selftests_dir="${kernel_checkout}/tools/testing/selftests/hid"9191-9292- cd "${selftests_dir}"9393- ${make_command}9494-}9595-9696-run_vm()9797-{9898- local run_dir="$1"9999- local b2c="$2"100100- local kernel_bzimage="$3"101101- local command="$4"102102- local post_command=""103103-104104- cd "${run_dir}"105105-106106- if ! which "${QEMU_BINARY}" &> /dev/null; then107107- cat <<EOF108108-Could not find ${QEMU_BINARY}109109-Please install qemu or set the QEMU_BINARY environment variable.110110-EOF111111- exit 1112112- fi113113-114114- # alpine (used in post-container requires the PATH to have /bin115115- export PATH=$PATH:/bin116116-117117- if [[ "${debug_shell}" != "yes" ]]118118- then119119- touch ${OUTPUT_DIR}/${LOG_FILE}120120- command="mount bpffs -t bpf /sys/fs/bpf/; set -o pipefail ; ${command} 2>&1 | tee ${OUTPUT_DIR}/${LOG_FILE}"121121- post_command="cat ${OUTPUT_DIR}/${LOG_FILE}"122122- else123123- command="mount bpffs -t bpf /sys/fs/bpf/; ${command}"124124- fi125125-126126- set +e127127- $b2c --command "${command}" \128128- --kernel ${kernel_bzimage} \129129- --workdir ${OUTPUT_DIR} \130130- --image ${CONTAINER_IMAGE}131131-132132- echo $? > ${OUTPUT_DIR}/${EXIT_STATUS_FILE}133133-134134- set -e135135-136136- ${post_command}137137-}138138-139139-is_rel_path()140140-{141141- local path="$1"142142-143143- [[ ${path:0:1} != "/" ]]144144-}145145-146146-do_update_kconfig()147147-{148148- local kernel_checkout="$1"149149- local kconfig_file="$2"150150-151151- rm -f "$kconfig_file" 2> /dev/null152152-153153- for config in "${KCONFIG_REL_PATHS[@]}"; do154154- local kconfig_src="${config}"155155- cat "$kconfig_src" >> "$kconfig_file"6363+ for ((i = 0; i < ${#TEST_NAMES[@]}; i++)); do6464+ name=${TEST_NAMES[${i}]}6565+ desc=${TEST_DESCS[${i}]}6666+ printf "\t%-35s%-35s\n" "${name}" "${desc}"15667 done6868+ echo6969+7070+ exit 115771}15872159159-update_kconfig()160160-{161161- local kernel_checkout="$1"162162- local kconfig_file="$2"7373+die() {7474+ echo "$*" >&27575+ exit "${KSFT_FAIL}"7676+}16377164164- if [[ -f "${kconfig_file}" ]]; then165165- local local_modified="$(stat -c %Y "${kconfig_file}")"7878+vm_ssh() {7979+ # vng --ssh-client keeps shouting "Warning: Permanently added 'virtme-ng%22'8080+ # (ED25519) to the list of known hosts.",8181+ # So replace the command with what's actually called and add the "-q" option8282+ stdbuf -oL ssh -q \8383+ -F ${HOME}/.cache/virtme-ng/.ssh/virtme-ng-ssh.conf \8484+ -l root virtme-ng%${SSH_GUEST_PORT} \8585+ "$@"8686+ return $?8787+}16688167167- for config in "${KCONFIG_REL_PATHS[@]}"; do168168- local kconfig_src="${config}"169169- local src_modified="$(stat -c %Y "${kconfig_src}")"170170- # Only update the config if it has been updated after the171171- # previously cached config was created. This avoids172172- # unnecessarily compiling the kernel and selftests.173173- if [[ "${src_modified}" -gt "${local_modified}" ]]; then174174- do_update_kconfig "$kernel_checkout" "$kconfig_file"175175- # Once we have found one outdated configuration176176- # there is no need to check other ones.8989+cleanup() {9090+ if [[ -s "${QEMU_PIDFILE}" ]]; then9191+ pkill -SIGTERM -F "${QEMU_PIDFILE}" > /dev/null 2>&19292+ fi9393+9494+ # If failure occurred during or before qemu start up, then we need9595+ # to clean this up ourselves.9696+ if [[ -e "${QEMU_PIDFILE}" ]]; then9797+ rm "${QEMU_PIDFILE}"9898+ fi9999+}100100+101101+check_args() {102102+ local found103103+104104+ for arg in "$@"; do105105+ found=0106106+ for name in "${TEST_NAMES[@]}"; do107107+ if [[ "${name}" = "${arg}" ]]; then108108+ found=1177109 break178110 fi179111 done180180- else181181- do_update_kconfig "$kernel_checkout" "$kconfig_file"182182- fi183183-}184112185185-main()186186-{187187- local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"188188- local kernel_checkout=$(realpath "${script_dir}"/../../../../)189189- # By default the script searches for the kernel in the checkout directory but190190- # it also obeys environment variables O= and KBUILD_OUTPUT=191191- local kernel_bzimage="${kernel_checkout}/${BZIMAGE}"192192- local command="${DEFAULT_COMMAND}"193193- local update_b2c="no"194194- local debug_shell="no"195195- local build_only="no"196196-197197- while getopts ':hsud:j:b' opt; do198198- case ${opt} in199199- u)200200- update_b2c="yes"201201- ;;202202- d)203203- OUTPUT_DIR="$OPTARG"204204- ;;205205- j)206206- NUM_COMPILE_JOBS="$OPTARG"207207- ;;208208- s)209209- command="/bin/sh"210210- debug_shell="yes"211211- ;;212212- b)213213- build_only="yes"214214- ;;215215- h)113113+ if [[ "${found}" -eq 0 ]]; then114114+ echo "${arg} is not an available test" >&2216115 usage217217- exit 0218218- ;;219219- \? )220220- echo "Invalid Option: -$OPTARG"221221- usage222222- exit 1223223- ;;224224- : )225225- echo "Invalid Option: -$OPTARG requires an argument"226226- usage227227- exit 1228228- ;;229229- esac116116+ fi230117 done231231- shift $((OPTIND -1))232118233233- # trap 'catch "$?"' EXIT234234- if [[ "${build_only}" == "no" && "${debug_shell}" == "no" ]]; then235235- if [[ $# -eq 0 ]]; then236236- echo "No command specified, will run ${DEFAULT_COMMAND} in the vm"237237- else238238- command="$@"239239-240240- if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]]241241- then242242- debug_shell="yes"243243- fi119119+ for arg in "$@"; do120120+ if ! command -v > /dev/null "test_${arg}"; then121121+ echo "Test ${arg} not found" >&2122122+ usage244123 fi124124+ done125125+}126126+127127+check_deps() {128128+ for dep in vng ${QEMU} busybox pkill ssh pytest; do129129+ if [[ ! -x $(command -v "${dep}") ]]; then130130+ echo -e "skip: dependency ${dep} not found!\n"131131+ exit "${KSFT_SKIP}"132132+ fi133133+ done134134+135135+ if [[ ! -x $(command -v "${HID_BPF_TEST}") ]]; then136136+ printf "skip: %s not found!" "${HID_BPF_TEST}"137137+ printf " Please build the kselftest hid_bpf target.\n"138138+ exit "${KSFT_SKIP}"245139 fi246140247247- local kconfig_file="${OUTPUT_DIR}/latest.config"248248- local make_command="make -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}"249249-250250- # Figure out where the kernel is being built.251251- # O takes precedence over KBUILD_OUTPUT.252252- if [[ "${O:=""}" != "" ]]; then253253- if is_rel_path "${O}"; then254254- O="$(realpath "${PWD}/${O}")"255255- fi256256- kernel_bzimage="${O}/${BZIMAGE}"257257- make_command="${make_command} O=${O}"258258- elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then259259- if is_rel_path "${KBUILD_OUTPUT}"; then260260- KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")"261261- fi262262- kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}"263263- make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}"264264- fi265265-266266- local b2c="${OUTPUT_DIR}/vm2c.py"267267-268268- echo "Output directory: ${OUTPUT_DIR}"269269-270270- mkdir -p "${OUTPUT_DIR}"271271- update_kconfig "${kernel_checkout}" "${kconfig_file}"272272-273273- recompile_kernel "${kernel_checkout}" "${make_command}"274274- update_selftests "${kernel_checkout}" "${make_command}"275275-276276- if [[ "${build_only}" == "no" ]]; then277277- if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then278278- echo "vm2c script not found in ${b2c}"279279- update_b2c="yes"280280- fi281281-282282- if [[ "${update_b2c}" == "yes" ]]; then283283- download $B2C_URL $b2c284284- chmod +x $b2c285285- fi286286-287287- run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}"288288- if [[ "${debug_shell}" != "yes" ]]; then289289- echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}"290290- fi291291-292292- exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE})141141+ if [[ ! -x $(command -v "${HIDRAW_TEST}") ]]; then142142+ printf "skip: %s not found!" "${HIDRAW_TEST}"143143+ printf " Please build the kselftest hidraw target.\n"144144+ exit "${KSFT_SKIP}"293145 fi294146}295147296296-main "$@"148148+check_vng() {149149+ local tested_versions150150+ local version151151+ local ok152152+153153+ tested_versions=("1.36" "1.37")154154+ version="$(vng --version)"155155+156156+ ok=0157157+ for tv in "${tested_versions[@]}"; do158158+ if [[ "${version}" == *"${tv}"* ]]; then159159+ ok=1160160+ break161161+ fi162162+ done163163+164164+ if [[ ! "${ok}" -eq 1 ]]; then165165+ printf "warning: vng version '%s' has not been tested and may " "${version}" >&2166166+ printf "not function properly.\n\tThe following versions have been tested: " >&2167167+ echo "${tested_versions[@]}" >&2168168+ fi169169+}170170+171171+handle_build() {172172+ if [[ ! "${BUILD}" -eq 1 ]]; then173173+ return174174+ fi175175+176176+ if [[ ! -d "${KERNEL_CHECKOUT}" ]]; then177177+ echo "-b requires vmtest.sh called from the kernel source tree" >&2178178+ exit 1179179+ fi180180+181181+ pushd "${KERNEL_CHECKOUT}" &>/dev/null182182+183183+ if ! vng --kconfig --config "${SCRIPT_DIR}"/config; then184184+ die "failed to generate .config for kernel source tree (${KERNEL_CHECKOUT})"185185+ fi186186+187187+ local vng_args=("-v" "--config" "${SCRIPT_DIR}/config" "--build")188188+189189+ if [[ -n "${BUILD_HOST}" ]]; then190190+ vng_args+=("--build-host" "${BUILD_HOST}")191191+ fi192192+193193+ if [[ -n "${BUILD_HOST_PODMAN_CONTAINER_NAME}" ]]; then194194+ vng_args+=("--build-host-exec-prefix" \195195+ "podman exec -ti ${BUILD_HOST_PODMAN_CONTAINER_NAME}")196196+ fi197197+198198+ if ! vng "${vng_args[@]}"; then199199+ die "failed to build kernel from source tree (${KERNEL_CHECKOUT})"200200+ fi201201+202202+ if ! make -j$(nproc) -C "${HID_BPF_PROGS}"; then203203+ die "failed to build HID bpf objects from source tree (${HID_BPF_PROGS})"204204+ fi205205+206206+ if ! make -j$(nproc) -C "${SCRIPT_DIR}"; then207207+ die "failed to build HID selftests from source tree (${SCRIPT_DIR})"208208+ fi209209+210210+ popd &>/dev/null211211+}212212+213213+vm_start() {214214+ local logfile=/dev/null215215+ local verbose_opt=""216216+ local kernel_opt=""217217+ local qemu218218+219219+ qemu=$(command -v "${QEMU}")220220+221221+ if [[ "${VERBOSE}" -eq 2 ]]; then222222+ verbose_opt="--verbose"223223+ logfile=/dev/stdout224224+ fi225225+226226+ # If we are running from within the kernel source tree, use the kernel source tree227227+ # as the kernel to boot, otherwise use the currently running kernel.228228+ if [[ "$(realpath "$(pwd)")" == "${KERNEL_CHECKOUT}"* ]]; then229229+ kernel_opt="${KERNEL_CHECKOUT}"230230+ fi231231+232232+ vng \233233+ --run \234234+ ${kernel_opt} \235235+ ${verbose_opt} \236236+ --qemu-opts="${QEMU_OPTS}" \237237+ --qemu="${qemu}" \238238+ --user root \239239+ --append "${KERNEL_CMDLINE}" \240240+ --ssh "${SSH_GUEST_PORT}" \241241+ --rw &> ${logfile} &242242+243243+ local vng_pid=$!244244+ local elapsed=0245245+246246+ while [[ ! -s "${QEMU_PIDFILE}" ]]; do247247+ if ! kill -0 "${vng_pid}" 2>/dev/null; then248248+ echo "vng process (PID ${vng_pid}) exited early, check logs for details" >&2249249+ die "failed to boot VM"250250+ fi251251+252252+ if [[ ${elapsed} -ge ${WAIT_TOTAL} ]]; then253253+ echo "Timed out after ${WAIT_TOTAL} seconds waiting for VM to boot" >&2254254+ die "failed to boot VM"255255+ fi256256+257257+ sleep 1258258+ elapsed=$((elapsed + 1))259259+ done260260+}261261+262262+vm_wait_for_ssh() {263263+ local i264264+265265+ i=0266266+ while true; do267267+ if [[ ${i} -gt ${WAIT_PERIOD_MAX} ]]; then268268+ die "Timed out waiting for guest ssh"269269+ fi270270+ if vm_ssh -- true; then271271+ break272272+ fi273273+ i=$(( i + 1 ))274274+ sleep ${WAIT_PERIOD}275275+ done276276+}277277+278278+vm_mount_bpffs() {279279+ vm_ssh -- mount bpffs -t bpf /sys/fs/bpf280280+}281281+282282+__log_stdin() {283283+ stdbuf -oL awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0; fflush() }'284284+}285285+286286+__log_args() {287287+ echo "$*" | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }'288288+}289289+290290+log() {291291+ local verbose="$1"292292+ shift293293+294294+ local prefix="$1"295295+296296+ shift297297+ local redirect=298298+ if [[ ${verbose} -le 0 ]]; then299299+ redirect=/dev/null300300+ else301301+ redirect=/dev/stdout302302+ fi303303+304304+ if [[ "$#" -eq 0 ]]; then305305+ __log_stdin | tee -a "${LOG}" > ${redirect}306306+ else307307+ __log_args "$@" | tee -a "${LOG}" > ${redirect}308308+ fi309309+}310310+311311+log_setup() {312312+ log $((VERBOSE-1)) "setup" "$@"313313+}314314+315315+log_host() {316316+ local testname=$1317317+318318+ shift319319+ log $((VERBOSE-1)) "test:${testname}:host" "$@"320320+}321321+322322+log_guest() {323323+ local testname=$1324324+325325+ shift326326+ log ${VERBOSE} "# test:${testname}" "$@"327327+}328328+329329+test_vm_hid_bpf() {330330+ local testname="${FUNCNAME[0]#test_}"331331+332332+ vm_ssh -- "${HID_BPF_TEST}" \333333+ 2>&1 | log_guest "${testname}"334334+335335+ return ${PIPESTATUS[0]}336336+}337337+338338+test_vm_hidraw() {339339+ local testname="${FUNCNAME[0]#test_}"340340+341341+ vm_ssh -- "${HIDRAW_TEST}" \342342+ 2>&1 | log_guest "${testname}"343343+344344+ return ${PIPESTATUS[0]}345345+}346346+347347+test_vm_pytest() {348348+ local testname="${FUNCNAME[0]#test_}"349349+350350+ shift351351+352352+ vm_ssh -- pytest ${SCRIPT_DIR}/tests --color=yes "$@" \353353+ 2>&1 | log_guest "${testname}"354354+355355+ return ${PIPESTATUS[0]}356356+}357357+358358+run_test() {359359+ local vm_oops_cnt_before360360+ local vm_warn_cnt_before361361+ local vm_oops_cnt_after362362+ local vm_warn_cnt_after363363+ local name364364+ local rc365365+366366+ vm_oops_cnt_before=$(vm_ssh -- dmesg | grep -c -i 'Oops')367367+ vm_error_cnt_before=$(vm_ssh -- dmesg --level=err | wc -l)368368+369369+ name=$(echo "${1}" | awk '{ print $1 }')370370+ eval test_"${name}" "$@"371371+ rc=$?372372+373373+ vm_oops_cnt_after=$(vm_ssh -- dmesg | grep -i 'Oops' | wc -l)374374+ if [[ ${vm_oops_cnt_after} -gt ${vm_oops_cnt_before} ]]; then375375+ echo "FAIL: kernel oops detected on vm" | log_host "${name}"376376+ rc=$KSFT_FAIL377377+ fi378378+379379+ vm_error_cnt_after=$(vm_ssh -- dmesg --level=err | wc -l)380380+ if [[ ${vm_error_cnt_after} -gt ${vm_error_cnt_before} ]]; then381381+ echo "FAIL: kernel error detected on vm" | log_host "${name}"382382+ vm_ssh -- dmesg --level=err | log_host "${name}"383383+ rc=$KSFT_FAIL384384+ fi385385+386386+ return "${rc}"387387+}388388+389389+QEMU="qemu-system-$(uname -m)"390390+391391+while getopts :hvsbq:H:p: o392392+do393393+ case $o in394394+ v) VERBOSE=$((VERBOSE+1));;395395+ s) SHELL_MODE=1;;396396+ b) BUILD=1;;397397+ q) QEMU=$OPTARG;;398398+ H) BUILD_HOST=$OPTARG;;399399+ p) BUILD_HOST_PODMAN_CONTAINER_NAME=$OPTARG;;400400+ h|*) usage;;401401+ esac402402+done403403+shift $((OPTIND-1))404404+405405+trap cleanup EXIT406406+407407+PARAMS=""408408+409409+if [[ ${#} -eq 0 ]]; then410410+ ARGS=("${TEST_NAMES[@]}")411411+else412412+ ARGS=()413413+ COUNT=0414414+ for arg in $@; do415415+ COUNT=$((COUNT+1))416416+ if [[ x"$arg" == x"--" ]]; then417417+ break418418+ fi419419+ ARGS+=($arg)420420+ done421421+ shift $COUNT422422+ PARAMS="$@"423423+fi424424+425425+if [[ "${SHELL_MODE}" -eq 0 ]]; then426426+ check_args "${ARGS[@]}"427427+ echo "1..${#ARGS[@]}"428428+fi429429+check_deps430430+check_vng431431+handle_build432432+433433+log_setup "Booting up VM"434434+vm_start435435+vm_wait_for_ssh436436+vm_mount_bpffs437437+log_setup "VM booted up"438438+439439+if [[ "${SHELL_MODE}" -eq 1 ]]; then440440+ log_setup "Starting interactive shell in VM"441441+ echo "Starting shell in VM. Use 'exit' to quit and shutdown the VM."442442+ CURRENT_DIR="$(pwd)"443443+ vm_ssh -t -- "cd '${CURRENT_DIR}' && exec bash -l"444444+ exit "$KSFT_PASS"445445+fi446446+447447+cnt_pass=0448448+cnt_fail=0449449+cnt_skip=0450450+cnt_total=0451451+for arg in "${ARGS[@]}"; do452452+ run_test "${arg}" "${PARAMS}"453453+ rc=$?454454+ if [[ ${rc} -eq $KSFT_PASS ]]; then455455+ cnt_pass=$(( cnt_pass + 1 ))456456+ echo "ok ${cnt_total} ${arg}"457457+ elif [[ ${rc} -eq $KSFT_SKIP ]]; then458458+ cnt_skip=$(( cnt_skip + 1 ))459459+ echo "ok ${cnt_total} ${arg} # SKIP"460460+ elif [[ ${rc} -eq $KSFT_FAIL ]]; then461461+ cnt_fail=$(( cnt_fail + 1 ))462462+ echo "not ok ${cnt_total} ${arg} # exit=$rc"463463+ fi464464+ cnt_total=$(( cnt_total + 1 ))465465+done466466+467467+echo "SUMMARY: PASS=${cnt_pass} SKIP=${cnt_skip} FAIL=${cnt_fail}"468468+echo "Log: ${LOG}"469469+470470+if [ $((cnt_pass + cnt_skip)) -eq ${cnt_total} ]; then471471+ exit "$KSFT_PASS"472472+else473473+ exit "$KSFT_FAIL"474474+fi