run-tests.sh (3910B)
1 #!/usr/bin/env bash 2 # Test the current package under a different kernel. 3 # Requires virtme and qemu to be installed. 4 # Examples: 5 # Run all tests on a 5.4 kernel 6 # $ ./run-tests.sh 5.4 7 # Run a subset of tests: 8 # $ ./run-tests.sh 5.4 ./link 9 10 set -euo pipefail 11 12 script="$(realpath "$0")" 13 readonly script 14 15 # This script is a bit like a Matryoshka doll since it keeps re-executing itself 16 # in various different contexts: 17 # 18 # 1. invoked by the user like run-tests.sh 5.4 19 # 2. invoked by go test like run-tests.sh --exec-vm 20 # 3. invoked by init in the vm like run-tests.sh --exec-test 21 # 22 # This allows us to use all available CPU on the host machine to compile our 23 # code, and then only use the VM to execute the test. This is because the VM 24 # is usually slower at compiling than the host. 25 if [[ "${1:-}" = "--exec-vm" ]]; then 26 shift 27 28 input="$1" 29 shift 30 31 # Use sudo if /dev/kvm isn't accessible by the current user. 32 sudo="" 33 if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then 34 sudo="sudo" 35 fi 36 readonly sudo 37 38 testdir="$(dirname "$1")" 39 output="$(mktemp -d)" 40 printf -v cmd "%q " "$@" 41 42 if [[ "$(stat -c '%t:%T' -L /proc/$$/fd/0)" == "1:3" ]]; then 43 # stdin is /dev/null, which doesn't play well with qemu. Use a fifo as a 44 # blocking substitute. 45 mkfifo "${output}/fake-stdin" 46 # Open for reading and writing to avoid blocking. 47 exec 0<> "${output}/fake-stdin" 48 rm "${output}/fake-stdin" 49 fi 50 51 for ((i = 0; i < 3; i++)); do 52 if ! $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \ 53 --rwdir="${testdir}=${testdir}" \ 54 --rodir=/run/input="${input}" \ 55 --rwdir=/run/output="${output}" \ 56 --script-sh "PATH=\"$PATH\" CI_MAX_KERNEL_VERSION="${CI_MAX_KERNEL_VERSION:-}" \"$script\" --exec-test $cmd" \ 57 --kopt possible_cpus=2; then # need at least two CPUs for some tests 58 exit 23 59 fi 60 61 if [[ -e "${output}/status" ]]; then 62 break 63 fi 64 65 if [[ -v CI ]]; then 66 echo "Retrying test run due to qemu crash" 67 continue 68 fi 69 70 exit 42 71 done 72 73 rc=$(<"${output}/status") 74 $sudo rm -r "$output" 75 exit $rc 76 elif [[ "${1:-}" = "--exec-test" ]]; then 77 shift 78 79 mount -t bpf bpf /sys/fs/bpf 80 mount -t tracefs tracefs /sys/kernel/debug/tracing 81 82 if [[ -d "/run/input/bpf" ]]; then 83 export KERNEL_SELFTESTS="/run/input/bpf" 84 fi 85 86 if [[ -f "/run/input/bpf/bpf_testmod/bpf_testmod.ko" ]]; then 87 insmod "/run/input/bpf/bpf_testmod/bpf_testmod.ko" 88 fi 89 90 dmesg --clear 91 rc=0 92 "$@" || rc=$? 93 dmesg 94 echo $rc > "/run/output/status" 95 exit $rc # this return code is "swallowed" by qemu 96 fi 97 98 readonly kernel_version="${1:-}" 99 if [[ -z "${kernel_version}" ]]; then 100 echo "Expecting kernel version as first argument" 101 exit 1 102 fi 103 shift 104 105 readonly kernel="linux-${kernel_version}.bz" 106 readonly selftests="linux-${kernel_version}-selftests-bpf.tgz" 107 readonly input="$(mktemp -d)" 108 readonly tmp_dir="${TMPDIR:-/tmp}" 109 readonly branch="${BRANCH:-master}" 110 111 fetch() { 112 echo Fetching "${1}" 113 pushd "${tmp_dir}" > /dev/null 114 curl -s -L -O --fail --etag-compare "${1}.etag" --etag-save "${1}.etag" "https://github.com/cilium/ci-kernels/raw/${branch}/${1}" 115 local ret=$? 116 popd > /dev/null 117 return $ret 118 } 119 120 fetch "${kernel}" 121 cp "${tmp_dir}/${kernel}" "${input}/bzImage" 122 123 if fetch "${selftests}"; then 124 echo "Decompressing selftests" 125 mkdir "${input}/bpf" 126 tar --strip-components=4 -xf "${tmp_dir}/${selftests}" -C "${input}/bpf" 127 else 128 echo "No selftests found, disabling" 129 fi 130 131 args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...) 132 if (( $# > 0 )); then 133 args=("$@") 134 fi 135 136 export GOFLAGS=-mod=readonly 137 export CGO_ENABLED=0 138 # LINUX_VERSION_CODE test compares this to discovered value. 139 export KERNEL_VERSION="${kernel_version}" 140 141 echo Testing on "${kernel_version}" 142 go test -exec "$script --exec-vm $input" "${args[@]}" 143 echo "Test successful on ${kernel_version}" 144 145 rm -r "${input}"