Make run_emu.sh into user-friendly run-test.sh
The script was meant to be a wrapper around QEMU that parses the result
of a kvm-unit-tests' instance from the logs. Make the script more useful
for users by adding new command-line flags and making most flags
optional.
Users can now run a single test case without having to wait for Make to
check if dependencies need to be rebuilt, run a test case with GDB
enabled, while still being able to provide a custom kernel and/or pass
flags directly to QEMU.
Example usage:
$ make -j40
$ build/kvm-unit-tests/run_test.sh -G psci # run with GDB
Change-Id: Icf4f4cf4d9f37f518e3621a5ab13814c4e54647a
diff --git a/aarch64-unit-tests/run_emu.sh b/aarch64-unit-tests/run_emu.sh
deleted file mode 100755
index 22f2d49..0000000
--- a/aarch64-unit-tests/run_emu.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2020 The Android KVM Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-TIMEOUT=180s
-RUN_QEMU_SCRIPT="$(dirname "${BASH_SOURCE[0]}")/../aarch64/run_qemu.sh"
-
-# QEMU CPUs to use for VHE and nVHE runs
-VHE_CPU="max"
-NVHE_CPU="cortex-a53"
-
-TEST_FILE=$1
-LINUX_KERNEL=$2
-ROOTFS=$3
-QEMU=$4
-VHE=$5
-LOG_FILE=$6
-TEST_NAME=$7
-CPU=""
-
-if [ ! -f "${TEST_FILE}" ]; then
- echo "Standalone kvmunittest file not found"
- echo "Run make standalone first to generate the standalone test files."
- exit 1
-fi
-
-if [ ! -f "${LINUX_KERNEL}" ]; then
- echo "Linux kernel image file not found."
- exit 1
-fi
-
-if [ ! -f "${ROOTFS}" ]; then
- echo "Root filesystem image file not found."
- exit 1
-fi
-
-if [ ! -x "${QEMU}" ]; then
- echo "QEMU executable not found."
- exit 1
-fi
-
-if [ "${VHE}" = 1 ]; then
- CPU=${VHE_CPU}
-else
- CPU=${NVHE_CPU}
-fi
-
-"${RUN_QEMU_SCRIPT}" \
- -e "${QEMU}" \
- -k "${LINUX_KERNEL}" \
- -r "${ROOTFS}" \
- -R "${TEST_FILE}" \
- -c "${CPU}" \
- -t "${TIMEOUT}" \
- &> "${LOG_FILE}"
-EXIT_STATUS=$?
-
-RESULT=$(grep -E -h --color=never "[^ ](PASS|FAIL|SKIP)[^:]" "${LOG_FILE}")
-if [ -z "${RESULT}" ]; then
- RESULT="\e[31;1mTIMEOUT/CRASH\e[0m"
- EXIT_STATUS=1
-fi
-
-echo -e "${TEST_NAME}: ${RESULT}"
-exit ${EXIT_STATUS}
diff --git a/aarch64-unit-tests/run_tests.sh b/aarch64-unit-tests/run_tests.sh
index 423b79f..c292d98 100755
--- a/aarch64-unit-tests/run_tests.sh
+++ b/aarch64-unit-tests/run_tests.sh
@@ -14,14 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
-# Variables to represent VHE and nVHE emulation parameter
-VHE=1
-NVHE=0
-
exit_status=0
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
test_dir=""
+test_script="${script_dir}/../kvm-unit-tests/run_test.sh"
log_dir=${LOG_DIR:-out/test/kvm-unit-tests}
exclude_regex=""
j=1
@@ -168,8 +164,16 @@
fi
# Redirect output instead of pipe to preserve exit status.
- run_job "${script_dir}/run_emu.sh ${test} ${linux} ${rootfs} ${qemu} ${VHE} ${log_dir}/logs/vhe/${test_name}.log \"${test_name} (vhe)\" &> >(tail -1)"
- run_job "${script_dir}/run_emu.sh ${test} ${linux} ${rootfs} ${qemu} ${NVHE} ${log_dir}/logs/nvhe/${test_name}.log \"${test_name} (nvhe)\" &> >(tail -1)"
+ run_job "${test_script} -V -k ${linux} \
+ -o ${log_dir}/logs/vhe/${test_name}.log \
+ -d \"${test_name} (vhe)\" ${test} \
+ -- -e ${qemu} -r ${rootfs} \
+ &> >(tail -1)"
+ run_job "${test_script} -k ${linux} \
+ -o ${log_dir}/logs/nvhe/${test_name}.log \
+ -d \"${test_name} (nvhe)\" ${test} \
+ -- -e ${qemu} -r ${rootfs} \
+ &> >(tail -1)"
done
wait_background_jobs
diff --git a/common.inc b/common.inc
index 7c7415a..29dfaa1 100644
--- a/common.inc
+++ b/common.inc
@@ -19,6 +19,8 @@
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
ROOT_DIR="$(dirname "${SCRIPT_DIR}")"
+SCRIPT_RUN_QEMU="${SCRIPT_DIR}/aarch64/run_qemu.sh"
+
PREBUILTS_DIR="${ROOT_DIR}/prebuilts"
PREBUILTS_IMG_DIR="${PREBUILTS_DIR}/linux-aarch64/images"
@@ -32,6 +34,9 @@
LINUX_OUT="${OUT_DIR}/linux"
LINUX_OUT_IMAGE="${LINUX_OUT}/arch/arm64/boot/Image.gz"
+KUT_OUT="${OUT_DIR}/kvm-unit-tests"
+KUT_TEST_DIR="${KUT_OUT}/tests"
+
# Define a variable with a given default value. Also defines
# variable DEFAULT_<name> with the default value.
# Args:
diff --git a/kvm-unit-tests/run_test.sh b/kvm-unit-tests/run_test.sh
new file mode 100755
index 0000000..0fbadda
--- /dev/null
+++ b/kvm-unit-tests/run_test.sh
@@ -0,0 +1,158 @@
+#!/usr/bin/env bash
+
+# Copyright 2020 The Android KVM Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source "$(dirname "${BASH_SOURCE[0]}")/../common.inc"
+
+default_var TIMEOUT 180s
+default_var VHE 0
+default_var VERBOSE 0
+default_var QUIET 0
+default_var GDB 0
+default_var KERNEL ""
+default_var TEST_PATH ""
+default_var DISPLAY_NAME ""
+default_var OUTPUT ""
+
+# QEMU CPUs to use for VHE and nVHE runs
+CPU_VHE="max"
+CPU_NVHE="cortex-a53"
+
+function usage() {
+ cat <<EOF
+
+Usage: $0 [-h] [-v] [-q] [-G] [-V]
+ [-k KERNEL] [-d DISPLAY_NAME] [-o OUTPUT]
+ PATH [-- RUN_QEMU_ARGS]
+
+ PATH Path to test binary. Basenames are resolved in the default output folder.
+ -h Output this help text
+ -v Print invoked command
+ -q Print only the result of the test
+ -k Kernel image
+ -d Override test name displayed in result
+ -o Redirect stdout/stderr output to given file (implies -q)
+ -V Enable VHE configuration
+ -G Enable debugging of emulated system with GDB
+EOF
+}
+
+while getopts ":k:d:o:vVGqh" OPT; do
+ case "${OPT}" in
+ k) KERNEL="${OPTARG}" ;;
+ d) DISPLAY_NAME="${OPTARG}" ;;
+ v) VERBOSE=1 ;;
+ V) VHE=1 ;;
+ q) QUIET=1 ;;
+ G) GDB=1 ;;
+ o)
+ OUTPUT="${OPTARG}"
+ QUIET=1
+ ;;
+ h)
+ usage
+ exit 0
+ ;;
+ \?)
+ echo "Invalid option: ${!OPTIND}" 1>&2
+ usage 1>&2
+ exit 1
+ ;;
+ :)
+ echo "Invalid option: -${OPTARG} requires an argument" 1>&2
+ usage 1>&2
+ exit 1
+ ;;
+ esac
+done
+shift $((OPTIND -1))
+
+# Parse test name from a positional argument.
+if [ $# -eq 0 ]; then
+ usage 1>&2
+ exit 1
+fi
+TEST_PATH="$1"
+shift 1
+
+# If there are arguments after "--", pass them to the underlying run_qemu.sh.
+RUN_QEMU_ARGS=()
+if [ $# -gt 0 ]; then
+ if [ $1 = "--" ]; then
+ shift 1
+ RUN_QEMU_ARGS=("$@")
+ else
+ echo "Unrecognized options: $@" 1>&2
+ usage 1>&2
+ exit 1
+ fi
+fi
+
+# Default display name is the basename from TEST_PATH.
+if [ -z "${DISPLAY_NAME}" ]; then
+ DISPLAY_NAME="$(basename "${TEST_PATH}")"
+fi
+
+# If TEST_PATH is just a basename, search for the test in
+# the kvm-unit-tests' default output folder.
+if [ "$(basename "${TEST_PATH}")" = "${TEST_PATH}" ]; then
+ TEST_PATH="${KUT_TEST_DIR}/${TEST_PATH}"
+fi
+
+CMD=("${SCRIPT_RUN_QEMU}" -R "${TEST_PATH}" -t "${TIMEOUT}")
+
+if [ "${VHE}" -eq 1 ]; then
+ CMD+=(-c "${CPU_VHE}")
+else
+ CMD+=(-c "${CPU_NVHE}")
+fi
+
+if [ -n "${KERNEL}" ]; then
+ CMD+=(-k "${KERNEL}")
+fi
+
+if [ "${GDB}" -eq 1 ]; then
+ CMD+=(-G)
+fi
+
+# Extra arguments passed directly to the underlying script.
+CMD+=("${RUN_QEMU_ARGS[@]}")
+
+# Disable exiting on failure.
+set +eo pipefail
+
+if [ "${VERBOSE}" -eq 1 ]; then
+ echo "+ ${CMD[@]}" 1>&2
+fi
+
+if [ "${QUIET}" -eq 0 ]; then
+ exec "${CMD[@]}"
+else
+ if [ -z "${OUTPUT}" ]; then
+ OUTPUT="$(mktemp)"
+ fi
+
+ "${CMD[@]}" &> "${OUTPUT}"
+ EXIT_STATUS=$?
+
+ RESULT=$(grep -E -h --color=never "[^ ](PASS|FAIL|SKIP)[^:]" "${OUTPUT}")
+ if [ -z "${RESULT}" ]; then
+ RESULT="\e[31;1mTIMEOUT/CRASH\e[0m"
+ EXIT_STATUS=1
+ fi
+
+ echo -e "${DISPLAY_NAME}: ${RESULT}"
+ exit ${EXIT_STATUS}
+fi