github.com/cilium/ebpf@v0.15.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  #     Run using a local kernel image
    10  #     $ ./run-tests.sh /path/to/bzImage
    11  
    12  set -euo pipefail
    13  
    14  script="$(realpath "$0")"
    15  readonly script
    16  
    17  source "$(dirname "$script")/testdata/sh/lib.sh"
    18  
    19  quote_env() {
    20    for var in "$@"; do
    21      if [ -v "$var" ]; then
    22        printf "%s=%q " "$var" "${!var}"
    23      fi
    24    done
    25  }
    26  
    27  declare -a preserved_env=(
    28    PATH
    29    CI_MAX_KERNEL_VERSION
    30    TEST_SEED
    31    KERNEL_VERSION
    32  )
    33  
    34  # This script is a bit like a Matryoshka doll since it keeps re-executing itself
    35  # in various different contexts:
    36  #
    37  #   1. invoked by the user like run-tests.sh 5.4
    38  #   2. invoked by go test like run-tests.sh --exec-vm
    39  #   3. invoked by init in the vm like run-tests.sh --exec-test
    40  #
    41  # This allows us to use all available CPU on the host machine to compile our
    42  # code, and then only use the VM to execute the test. This is because the VM
    43  # is usually slower at compiling than the host.
    44  if [[ "${1:-}" = "--exec-vm" ]]; then
    45    shift
    46  
    47    input="$1"
    48    shift
    49  
    50    # Use sudo if /dev/kvm isn't accessible by the current user.
    51    sudo=""
    52    if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then
    53      sudo="sudo"
    54    fi
    55    readonly sudo
    56  
    57    testdir="$(dirname "$1")"
    58    output="$(mktemp -d)"
    59    printf -v cmd "%q " "$@"
    60  
    61    if [[ "$(stat -c '%t:%T' -L /proc/$$/fd/0)" == "1:3" ]]; then
    62      # stdin is /dev/null, which doesn't play well with qemu. Use a fifo as a
    63      # blocking substitute.
    64      mkfifo "${output}/fake-stdin"
    65      # Open for reading and writing to avoid blocking.
    66      exec 0<> "${output}/fake-stdin"
    67      rm "${output}/fake-stdin"
    68    fi
    69  
    70    if ! $sudo virtme-run --kimg "${input}/boot/vmlinuz" --cpus 2 --memory 1G --pwd \
    71      --rwdir="${testdir}=${testdir}" \
    72      --rodir=/run/input="${input}" \
    73      --rwdir=/run/output="${output}" \
    74      --script-sh "$(quote_env "${preserved_env[@]}") \"$script\" \
    75      --exec-test $cmd"; then
    76      exit 23
    77    fi
    78  
    79    if ! [[ -e "${output}/status" ]]; then
    80      exit 42
    81    fi
    82  
    83    rc=$(<"${output}/status")
    84    $sudo rm -r "$output"
    85    exit "$rc"
    86  elif [[ "${1:-}" = "--exec-test" ]]; then
    87    shift
    88  
    89    mount -t bpf bpf /sys/fs/bpf
    90    mount -t tracefs tracefs /sys/kernel/debug/tracing
    91  
    92    if [[ -d "/run/input/usr/src/linux/tools/testing/selftests/bpf" ]]; then
    93      export KERNEL_SELFTESTS="/run/input/usr/src/linux/tools/testing/selftests/bpf"
    94    fi
    95  
    96    if [[ -d "/run/input/lib/modules" ]]; then
    97      find /run/input/lib/modules -type f -name bpf_testmod.ko -exec insmod {} \;
    98    fi
    99  
   100    dmesg --clear
   101    rc=0
   102    "$@" || rc=$?
   103    dmesg
   104    echo $rc > "/run/output/status"
   105    exit $rc # this return code is "swallowed" by qemu
   106  fi
   107  
   108  if [[ -z "${1:-}" ]]; then
   109    echo "Expecting kernel version or path as first argument"
   110    exit 1
   111  fi
   112  
   113  input="$(mktemp -d)"
   114  readonly input
   115  
   116  if [[ -f "${1}" ]]; then
   117    # First argument is a local file.
   118    readonly kernel="${1}"
   119    cp "${1}" "${input}/boot/vmlinuz"
   120  else
   121    readonly kernel="${1}"
   122  
   123    # LINUX_VERSION_CODE test compares this to discovered value.
   124    export KERNEL_VERSION="${1}"
   125  
   126    if ! extract_oci_image "ghcr.io/cilium/ci-kernels:${kernel}-selftests" "${input}"; then
   127      extract_oci_image "ghcr.io/cilium/ci-kernels:${kernel}" "${input}"
   128    fi
   129  fi
   130  shift
   131  
   132  args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
   133  if (( $# > 0 )); then
   134    args=("$@")
   135  fi
   136  
   137  export GOFLAGS=-mod=readonly
   138  export CGO_ENABLED=0
   139  
   140  echo Testing on "${kernel}"
   141  go test -exec "$script --exec-vm $input" "${args[@]}"
   142  echo "Test successful on ${kernel}"
   143  
   144  rm -r "${input}"