diff --git a/.github/workflows/scripts_tests.yml b/.github/workflows/scripts_tests.yml index 0ce3a3a..4b56430 100644 --- a/.github/workflows/scripts_tests.yml +++ b/.github/workflows/scripts_tests.yml @@ -8,11 +8,11 @@ on: - master jobs: - test_run_qemu: - name: Test run-qemu + test_run_vmtest: + name: Test run-vmtest runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - name: Test print_test_summary - run: ./run-qemu/print_test_summary.py -j run-qemu/fixtures/test_progs.json -s "${GITHUB_STEP_SUMMARY}" + run: ./run-vmtest/print_test_summary.py -j run-vmtest/fixtures/test_progs.json -s "${GITHUB_STEP_SUMMARY}" diff --git a/run-qemu/run.sh b/run-qemu/run.sh index 572667f..75f88ad 100755 --- a/run-qemu/run.sh +++ b/run-qemu/run.sh @@ -111,7 +111,7 @@ then if [ $? ] then ## Job summary - "${GITHUB_ACTION_PATH}/print_test_summary.py" -s "${GITHUB_STEP_SUMMARY}" -j "${KERNEL_TEST}.json" + "${GITHUB_ACTION_PATH}/../run-vmtest/print_test_summary.py" -s "${GITHUB_STEP_SUMMARY}" -j "${KERNEL_TEST}.json" fi fi diff --git a/run-vmtest/action.yml b/run-vmtest/action.yml new file mode 100644 index 0000000..4eb68d8 --- /dev/null +++ b/run-vmtest/action.yml @@ -0,0 +1,64 @@ +name: 'run vmtest' +description: 'Run vmtest and print summary' +inputs: + arch: + description: 'arch' + required: true + img: + description: 'img path' + required: true + vmlinuz: + description: 'vmlinuz path' + required: true + kernel-root: + description: 'kernel source dir' + default: '.' + max-cpu: + description: 'Maximum number of CPU allocated to a VM (regardless of number of CPUs available on the host). Default is unset, e.g it will default to the number of CPU on the host.' + default: '' + kernel-test: + description: 'Test to run' + default: '' + output-dir: + description: | + Some sub-commands produce output dir within VM file system (/command_output/). + If this option is set that dir's content would be copied to corresponding location. + default: '' +runs: + using: "composite" + steps: + - name: Find kernel + id: find-kernel + shell: bash + run: | + BUILDDIR=$(realpath kbuild-output) + vmlinuz="$BUILDDIR/$(KBUILD_OUTPUT="${BUILDDIR}" make -C "${{ inputs.kernel-root }}" -s image_name)" + cp "$vmlinuz" ${{ inputs.vmlinuz }} + - name: Download vmtest + shell: bash + # FIXME: move to proper release + run: | + curl -L https://github.com/chantra/danobi-vmtest/releases/download/v2.2.0/vmtest-$(uname -m) > /usr/bin/vmtest && chmod 755 /usr/bin/vmtest + - name: install qemu tools and selftest dependencies + shell: bash + run: | + source "${GITHUB_ACTION_PATH}/../helpers.sh" + foldable start install_qemu "Installing QEMU tools" + # need gawk to support `--field-separator` + sudo apt-get update && sudo apt-get install -y cpu-checker qemu-kvm qemu-utils qemu-system-x86 qemu-system-s390x qemu-system-arm qemu-guest-agent \ + ethtool keyutils iptables \ + gawk + foldable end install_qemu + - name: Run vmtest + shell: bash + env: + VMLINUZ: ${{ inputs.vmlinuz }} + IMG: ${{ inputs.img }} + KERNEL_ROOT: ${{ inputs.kernel-root }} + MAX_CPU: ${{ inputs.max-cpu }} + KERNEL_TEST: ${{ inputs.kernel-test }} + OUTPUT_DIR: ${{ inputs.output-dir }} + PROJECT_NAME: "/mnt/vmtest" + run: | + ${GITHUB_ACTION_PATH}/run.sh + diff --git a/run-qemu/fixtures/test_progs.json b/run-vmtest/fixtures/test_progs.json similarity index 100% rename from run-qemu/fixtures/test_progs.json rename to run-vmtest/fixtures/test_progs.json diff --git a/run-qemu/print_test_summary.py b/run-vmtest/print_test_summary.py similarity index 93% rename from run-qemu/print_test_summary.py rename to run-vmtest/print_test_summary.py index 59daf63..412323f 100755 --- a/run-qemu/print_test_summary.py +++ b/run-vmtest/print_test_summary.py @@ -3,9 +3,9 @@ # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary # # To test the output of the GH test summary: -# python3 run-qemu/print_test_summary.py -j run-qemu/fixtures/test_progs.json -s /dev/stderr > /dev/null +# python3 run-vmtest/print_test_summary.py -j run-vmtest/fixtures/test_progs.json -s /dev/stderr > /dev/null # To test the output of the console: -# python3 run-qemu/print_test_summary.py -j run-qemu/fixtures/test_progs.json -s /dev/stderr 2> /dev/null +# python3 run-vmtest/print_test_summary.py -j run-vmtest/fixtures/test_progs.json -s /dev/stderr 2> /dev/null import argparse import json diff --git a/run-vmtest/run.sh b/run-vmtest/run.sh new file mode 100755 index 0000000..1b8b44e --- /dev/null +++ b/run-vmtest/run.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +set -euo pipefail +trap 'exit 2' ERR + +source $(cd $(dirname $0) && pwd)/../helpers.sh + +foldable start bpftool_checks "Running bpftool checks..." +bpftool_exitstatus=0 + +# bpftool checks are aimed at checking type names, documentation, shell +# completion etc. against the current kernel, so only run on LATEST. +if [[ "${KERNEL}" = 'LATEST' ]]; then + # "&& true" does not change the return code (it is not executed if the + # Python script fails), but it prevents the trap on ERR set at the top + # of this file to trigger on failure. + "${REPO_ROOT}/${KERNEL_ROOT}/tools/testing/selftests/bpf/test_bpftool_synctypes.py" && true + bpftool_exitstatus=$? + if [[ $bpftool_exitstatus -eq 0 ]]; then + echo "bpftool checks passed successfully." + else + echo "bpftool checks returned ${bpftool_exitstatus}." + fi +else + echo "bpftool checks skipped." +fi + +bpftool_exitstatus="bpftool:${bpftool_exitstatus}" +foldable end bpftool_checks + +foldable start vmtest "Starting virtual machine..." + +# Tests may be comma-separated. vmtest_selftest expect them to come from CLI space-separated. +T=$(echo ${KERNEL_TEST} | tr -s ',' ' ') +# HACK: We need to unmount /tmp to access /tmp from the container.... +vmtest -k "${VMLINUZ}" --kargs "panic=-1 sysctl.vm.panic_on_oom=1" "umount /tmp && \ + /bin/mount bpffs /sys/fs/bpf -t bpf && \ + ip link set lo up && \ + cd '${GITHUB_WORKSPACE}' && \ + ./ci/vmtest/vmtest_selftests.sh ${T}" + +foldable end vmtest + +foldable start collect_status "Collecting exit status" + +exitfile="${bpftool_exitstatus}\n" +exitfile+="$(cat exitstatus 2>/dev/null)" +exitstatus="$(echo -e "$exitfile" | awk --field-separator ':' \ + 'BEGIN { s=0 } { if ($2) {s=1} } END { print s }')" + +if [[ "$exitstatus" =~ ^[0-9]+$ ]]; then + printf '\nTests exit status: %s\n' "$exitstatus" >&2 +else + printf '\nCould not read tests exit status ("%s")\n' "$exitstatus" >&2 + exitstatus=1 +fi + +foldable end collect_status + +# Try to collect json summary from VM +if [[ -n ${KERNEL_TEST} && ${KERNEL_TEST} =~ test_progs* ]] +then + ## Job summary + "${GITHUB_ACTION_PATH}/print_test_summary.py" -s "${GITHUB_STEP_SUMMARY}" -j "${KERNEL_TEST}.json" +fi + +# Final summary - Don't use a fold, keep it visible +echo -e "\033[1;33mTest Results:\033[0m" +echo -e "$exitfile" | while read result; do + testgroup=${result%:*} + status=${result#*:} + # Print final result for each group of tests + if [[ "$status" -eq 0 ]]; then + printf "%20s: \033[1;32mPASS\033[0m\n" "$testgroup" + else + printf "%20s: \033[1;31mFAIL\033[0m (returned %s)\n" "$testgroup" "$status" + fi +done + +exit "$exitstatus"