github.com/cilium/ebpf@v0.10.0/run-tests.sh (about)

     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 --no-progress-meter -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}"