tests: Run KMS tests inside a QEMU virtual machine

This commit makes it possible to run test executables in a test
environment constructed of a virtual machine running the Linux kernel
with the virtual KMS driver enabled, and a mocked system environment
using meta-dbus-runner.py/python-dbusmock.

The qemu machine is configured to use 256M of memory, as the default
128M was not enough for the tests to pass.

Using qemu is also only made possible on x86_64; more changes are needed
for it to be runnable on aarch64, so add a warning if it was enabled on
any other architecture.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2151>
This commit is contained in:
Jonas Ådahl 2021-12-10 23:49:48 +01:00 committed by Marge Bot
parent b5284e5ccc
commit 06eb27d503
9 changed files with 235 additions and 7 deletions

View File

@ -57,6 +57,7 @@ sysprof_req = '>= 3.37.2'
gnome = import('gnome') gnome = import('gnome')
pkg = import('pkgconfig') pkg = import('pkgconfig')
i18n = import('i18n') i18n = import('i18n')
fs = import('fs')
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
prefix = get_option('prefix') prefix = get_option('prefix')
@ -269,6 +270,7 @@ have_core_tests = false
have_cogl_tests = false have_cogl_tests = false
have_clutter_tests = false have_clutter_tests = false
have_native_tests = false have_native_tests = false
have_kvm_tests = false
have_installed_tests = false have_installed_tests = false
if have_tests if have_tests
@ -287,6 +289,15 @@ if have_tests
error('Native tests require remote desktop') error('Native tests require remote desktop')
endif endif
endif endif
have_kvm_tests = get_option('kvm_tests')
if have_kvm_tests
if not have_native_backend
error('KVM tests need the native backend tests')
endif
if host_machine.cpu_family() != 'x86_64'
error('KVM tests are only supported on x86_64')
endif
endif
have_cogl_tests = get_option('cogl_tests') have_cogl_tests = get_option('cogl_tests')
have_clutter_tests = get_option('clutter_tests') have_clutter_tests = get_option('clutter_tests')

View File

@ -141,6 +141,18 @@ option('tests',
description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests' description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests'
) )
option('kvm_tests',
type: 'boolean',
value: false,
description: 'Enable running certain tests in a virtual machine with a custom built kernel'
)
option('kvm_kernel_image',
type: 'string',
value: '',
description: 'Path to a Linux kernel image to be used for KVM testing'
)
option('profiler', option('profiler',
type: 'boolean', type: 'boolean',
value: true, value: true,

29
src/tests/kvm/README.md Normal file
View File

@ -0,0 +1,29 @@
## High level description of the files in this directory.
### build-linux.sh
Builds a Linux kernel image meant to be launched using qemu. Doesn't make any
assumptions about configuration other than that. It uses the drm kernel tree.
It's used from meson.build.
### kernel-version.txt
Describes the version of the Linux kernel to use; usually a tag. It's a
separate file so that changing the version will make meson build a new kernel
image.
### virtme-run.sh
A helper script that uses 'virtme' to launch a qemu virtual machine with the
host filesystem exposed inside the virtual machine.
### run-kvm-test.sh
Runs the passed test executable in a mocked environment using
'meta-dbus-runner.py' (which uses python-dbusmock to create a mocked system
environment.
### meson.build
Contains one rule for building the Linux kernel image, and meson test cases
that launches tests inside virtual machines.

74
src/tests/kvm/build-linux.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/bash
#
# Script for building the Linux kernel from git. It aims to build a kernel image
# that is suitable for running in a virtual machine and is aimed to used for
# testing.
#
# Usage: build-linux.sh [REPO-URL] [BRANCH|TAG] [OUTPUT-FILE] [...CONFIGS]
#
# Where [..CONFIGS] can be any number of configuration options, e.g.
# --enable CONFIG_DRM_VKMS
set -e
# From scripts/subarch.include in linux
function get-subarch()
{
uname -m | sed -e s/i.86/x86/ \
-e s/x86_64/x86/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
-e s/riscv.*/riscv/
}
REPO="$1"
BRANCH_OR_TAG="$(cat $2)"
IMAGE="$3"
ARCH=$(uname -m)
SUBARCH=$(get-subarch)
shift
shift
shift
# ./scripts/config --enable CONFIG_DRM_VKMS
CONFIGS=()
while [[ "x$1" != "x" ]]; do
CONFIGS+=( "$1" )
shift
done
echo Building Linux for $ARCH \($SUBARCH\)...
set -x
if [ -d linux ]; then
pushd linux
git fetch $REPO $BRANCH_OR_TAG
git checkout FETCH_HEAD
else
git clone --depth=1 --branch=$BRANCH_OR_TAG $REPO linux
pushd linux
fi
make defconfig
sync
make kvm_guest.config
echo Enabling ${CONFIGS[@]}...
./scripts/config ${CONFIGS[@]/#/--enable }
make oldconfig
make -j8
popd
TARGET_DIR="$(dirname "$IMAGE")"
mkdir -p "$TARGET_DIR"
mv linux/arch/$SUBARCH/boot/bzImage "$IMAGE"
mv linux/.config $TARGET_DIR/.config
#rm -rf linux

View File

@ -0,0 +1 @@
drm-next-2021-11-12

48
src/tests/kvm/meson.build Normal file
View File

@ -0,0 +1,48 @@
build_linux = find_program('build-linux.sh')
kernel_image_path = get_option('kvm_kernel_image')
if kernel_image_path != ''
if not fs.is_absolute(kernel_image_path)
error('Kernel image path @0@ must be absolute'.format(kernel_image_path))
endif
if not fs.is_file(kernel_image_path)
error('Kernel image @0@ does not exist'.format(kernel_image_path))
endif
kernel_image_target = []
else
kernel_image_target = custom_target('linux-kernel',
output: 'bzImage',
input: 'kernel-version.txt',
console: true,
command: [
build_linux,
'https://anongit.freedesktop.org/git/drm/drm.git',
'@INPUT@',
'@OUTPUT@',
'--enable', 'CONFIG_DRM_VKMS',
]
)
kernel_image_path = kernel_image_target.full_path()
endif
virtme_run = find_program('virtme-run.sh')
foreach test: privileged_tests
test_name = test[0]
test_executable = test[1]
test('kvm-' + test_name, virtme_run,
suite: ['core', 'mutter/native/kvm'],
depends: [
kernel_image_target,
],
workdir: mutter_srcdir,
args: [
kernel_image_path,
meta_dbus_runner.full_path(),
'--kvm',
test_executable.full_path(),
meson.current_build_dir(),
]
)
endforeach

23
src/tests/kvm/run-kvm-test.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/bash
set -e
WRAPPER="$1"
WRAPPER_ARGS="$2"
TEST_EXECUTABLE="$3"
TEST_RESULT="$4"
export XDG_RUNTIME_DIR="/tmp/sub-runtime-dir-$UID"
export GSETTINGS_SCHEMA_DIR="$PWD/build/data"
export G_SLICE="always-malloc"
export MALLOC_CHECK_="3"
export NO_AT_BRIDGE="1"
export MALLOC_PERTURB_="123"
mkdir -p -m 700 $XDG_RUNTIME_DIR
glib-compile-schemas $GSETTINGS_SCHEMA_DIR
"$WRAPPER" $WRAPPER_ARGS "$TEST_EXECUTABLE"
echo $? > $TEST_RESULT

25
src/tests/kvm/virtme-run.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/bash
set -e
DIRNAME="$(dirname "$0")"
IMAGE="$1"
WRAPPER="$2"
WRAPPER_ARGS="$3"
TEST_EXECUTABLE="$4"
TEST_BUILD_DIR="$5"
TEST_RESULT_FILE=$(mktemp -p "$TEST_BUILD_DIR" -t test-result-XXXXXX)
echo 1 > "$TEST_RESULT_FILE"
virtme-run \
--memory=256M \
--rw \
--pwd \
--kimg "$IMAGE" \
--script-sh "sh -c \"env HOME=$HOME $DIRNAME/run-kvm-test.sh \\\"$WRAPPER\\\" \\\"$WRAPPER_ARGS\\\" \\\"$TEST_EXECUTABLE\\\" \\\"$TEST_RESULT_FILE\\\"\""
TEST_RESULT="$(cat "$TEST_RESULT_FILE")"
rm "$TEST_RESULT_FILE"
exit "$TEST_RESULT"

View File

@ -117,6 +117,8 @@ test_runner = executable('mutter-test-runner',
install_dir: mutter_installed_tests_libexecdir, install_dir: mutter_installed_tests_libexecdir,
) )
meta_dbus_runner = find_program('meta-dbus-runner.py')
if have_installed_tests if have_installed_tests
install_data('meta-dbus-runner.py', install_data('meta-dbus-runner.py',
install_dir: mutter_installed_tests_libexecdir, install_dir: mutter_installed_tests_libexecdir,
@ -391,11 +393,14 @@ if have_native_tests
is_parallel: false, is_parallel: false,
timeout: 60, timeout: 60,
) )
endif
test('native-kms-render', native_kms_render_tests,
suite: ['core', 'mutter/native/kms/render'], if have_kvm_tests
env: test_env, privileged_tests = [
is_parallel: false, [ 'kms-render', native_kms_render_tests ],
timeout: 60, ]
)
if have_kvm_tests
subdir('kvm')
endif
endif endif