Back to Cloud Hypervisor

Testing

docs/testing.md

52.013.8 KB
Original Source

Testing

Overview

All Cloud Hypervisor builds and tests run inside a Docker container to provide a reproducible environment. The main entry point is scripts/dev_cli.sh, which manages the container lifecycle and forwards arguments to the appropriate test scripts.

The container image is published at ghcr.io/cloud-hypervisor/cloud-hypervisor and is automatically pulled on first use. A local build of the container can be triggered with scripts/dev_cli.sh build-container or by passing the --local flag.

Test workloads (guest images, kernels, firmware) are stored on the host under $HOME/workloads and bind-mounted into the container at /root/workloads. Most test scripts download missing workloads automatically on first run.

Prerequisites

A working Docker (or Podman) installation and access to /dev/kvm (or /dev/mshv for Microsoft Hypervisor tests) are required. The host must be running Linux on x86_64 or aarch64.

shell
# Verify KVM is available
ls -l /dev/kvm

The container image bundles all build dependencies. No Rust toolchain is needed on the host.

The dev_cli.sh entry point

scripts/dev_cli.sh [flags] <command> [<command args>]

Global flags

FlagDescription
--localBuild and use a local container image instead of pulling from the registry.

Building

shell
scripts/dev_cli.sh build [--debug|--release] [--libc musl|gnu] \
    [--hypervisor kvm|mshv] [--features <features>] \
    [--volumes /host:/ctr#...] [-- <cargo args>]
FlagDefaultDescription
--debugyesBuild debug binaries.
--releaseBuild release binaries.
--libcgnuC library to link against (musl/gnu).
--hypervisorkvmHypervisor backend (kvm/mshv).
--featuresAdditional cargo features.
--volumesExtra host volumes (/a:/a#/b:/b).
--runtimedockerContainer runtime (docker/podman).

Arguments after -- are forwarded directly to cargo build.

Running tests

shell
scripts/dev_cli.sh tests [<test type>] [--libc musl|gnu] \
    [--hypervisor kvm|mshv] [--volumes /host:/ctr#...] \
    [-- <script args> [-- <binary args>]]

Test type flags:

FlagDescription
--unitRun unit tests.
--integrationRun integration tests (includes live migration).
--integration-vfioRun VFIO integration tests.
--integration-windowsRun Windows guest integration tests.
--integration-rate-limiterRun rate limiter integration tests.
--integration-cvmRun confidential VM integration tests.
--metricsGenerate performance metrics.
--coverageGenerate code coverage.
--allRun both unit and integration tests.

Configuration flags:

FlagDefaultDescription
--libcgnuC library to link against (musl/gnu).
--hypervisorkvmHypervisor backend (kvm/mshv).
--volumesExtra host volumes (/a:/a#/b:/b).

Argument passthrough

The -- separator creates layers of argument forwarding:

dev_cli.sh tests <flags> -- <script args> -- <binary args>
  1. Everything before the first -- is consumed by dev_cli.sh.
  2. Everything between the first and second -- is forwarded to the test script (e.g., run_integration_tests_x86_64.sh).
  3. Everything after the second -- is forwarded to the test binary itself (e.g., performance-metrics).

The test scripts accept the following common arguments via process_common_args() in scripts/test-util.sh:

ArgumentDescription
--hypervisor kvm|mshvSelect hypervisor (also passed by dev_cli.sh).
--test-filter <name>Run only tests matching the filter.
--test-exclude <name>Exclude tests matching the pattern.
--build-guest-kernelBuild the guest kernel from source instead of downloading a prebuilt binary.

Example — run a single integration test:

shell
scripts/dev_cli.sh tests --integration \
    -- --test-filter test_boot_from_virtio_pmem

Example — run metrics excluding micro-benchmarks:

shell
scripts/dev_cli.sh tests --metrics \
    -- --test-exclude micro_ \
    -- --report-file /root/workloads/metrics.json

Custom kernel and firmware

The following environment variables allow overriding the default guest kernel or firmware binaries. Each variable is independent; set any combination without affecting the others.

VariableDescription
CH_CUSTOM_KERNELPath to a custom vmlinux (x86_64) or Image (aarch64) kernel binary.
CH_CUSTOM_FIRMWAREPath to a custom hypervisor-fw firmware binary.
CH_CUSTOM_OVMFPath to a custom OVMF binary (CLOUDHV.fd on x86_64, CLOUDHV_EFI.fd on aarch64).

The paths refer to locations on the host. Before launching the Docker container, dev_cli.sh copies the referenced files into $HOME/workloads at the default names the test scripts expect (e.g., vmlinux-x86_64, hypervisor-fw, CLOUDHV.fd). Because the workloads directory is bind-mounted into the container, the existing download-if-missing guards inside the test scripts automatically skip the network fetch.

shell
# Use a custom kernel for integration tests
CH_CUSTOM_KERNEL=/path/to/vmlinux \
    scripts/dev_cli.sh tests --integration

# Override all three
CH_CUSTOM_KERNEL=/path/to/vmlinux \
CH_CUSTOM_FIRMWARE=/path/to/hypervisor-fw \
CH_CUSTOM_OVMF=/path/to/CLOUDHV.fd \
    scripts/dev_cli.sh tests --integration

Unit tests

shell
scripts/dev_cli.sh tests --unit [--libc musl|gnu] [--hypervisor kvm|mshv]

Unit tests run cargo test on the entire workspace in release mode:

cargo test --lib --bins --target <target> --release --workspace
cargo test --doc --target <target> --release --workspace

The container is not fully privileged. It receives --device /dev/kvm (or /dev/mshv), --device /dev/net/tun, and --cap-add net_admin so that tests requiring a hypervisor device or TAP interfaces can run.

When the hypervisor is mshv, the feature flag --features mshv is passed to cargo. On x86_64 with KVM, the tdx feature is additionally enabled if needed (MSHV does not support TDX).

Integration tests

All integration test containers run with --privileged and full access to /dev. Workloads are bind-mounted from the host.

Test scripts use cargo nextest run with the --release profile. Tests are grouped by module name filter (e.g., common_parallel, common_sequential). Most groups support automatic retries (default 3). The nextest configuration in .config/nextest.toml sets a slow-timeout of 60 seconds per period with automatic termination after 10 periods (i.e., any single test running longer than 10 minutes is terminated).

The Rust test modules are defined in cloud-hypervisor/tests/integration.rs:

ModuleDescription
common_parallelMain tests run in parallel, including live migration.
common_sequentialTests requiring serial execution (snapshot/restore, OVS-DPDK live migration).
dbus_apiD-Bus API tests (requires dbus_api feature).
fw_cfgFirmware configuration tests (requires fw_cfg feature).
ivshmemInter-VM shared memory tests (requires ivshmem feature).
aarch64_acpiARM64 ACPI-specific tests.
windowsWindows guest tests.
vfioVFIO passthrough tests (x86_64 only).
rate_limiterNetwork/block rate limiting tests.

Confidential VM tests are in a separate file (cloud-hypervisor/tests/integration_cvm.rs) under the common_cvm module.

x86_64

shell
scripts/dev_cli.sh tests --integration [--libc musl|gnu]

Runs scripts/run_integration_tests_x86_64.sh. The script automatically downloads and prepares all required workloads:

  • Kernel: vmlinux-x86_64 (prebuilt or built from source with --build-guest-kernel).
  • Firmware: hypervisor-fw (rust-hypervisor-firmware).
  • OVMF: CLOUDHV.fd.
  • Guest images: Ubuntu Focal and Jammy cloud images in multiple formats (raw, qcow2, compressed, backing-file variants).
  • Alpine: Minirootfs and initramfs for lightweight boot tests.
  • virtiofsd: Built from source for virtio-fs tests.

System tuning applied inside the container:

  • KSM (Kernel Same-page Merging) is enabled.
  • 2 MiB hugepages are allocated for DPDK/VDPA tests.
  • The open file descriptor limit is raised to 4096.

Test groups executed: common_parallel, common_sequential, dbus_api, fw_cfg, ivshmem.

The dbus_api, fw_cfg, and ivshmem groups are each built with their respective cargo feature enabled before running.

Live migration tests (test_live_migration_*, test_live_upgrade_*) run as part of the common_parallel and common_sequential groups.

ARM64

shell
scripts/dev_cli.sh tests --integration --libc musl

Runs scripts/run_integration_tests_aarch64.sh. The workload setup mirrors x86_64 with aarch64-specific images:

  • Kernel: Image-arm64.
  • OVMF: CLOUDHV_EFI.fd.
  • Guest images: Focal and Jammy aarch64 cloud images.

Test groups executed: common_parallel, common_sequential, aarch64_acpi, dbus_api, fw_cfg, ivshmem.

VFIO

shell
scripts/dev_cli.sh tests --integration-vfio

Runs scripts/run_integration_tests_vfio.sh. Requires dedicated hardware with an Nvidia GPU (Tesla T4) for VFIO passthrough testing.

Test groups executed (single-threaded):

GroupDescription
vfio::test_nvidiaLegacy VFIO with container/group interface.
vfio::test_iommufdVFIO with cdev interface via iommufd.

Windows guests

shell
scripts/dev_cli.sh tests --integration-windows [--libc musl|gnu]

Runs the architecture-appropriate script:

  • x86_64: scripts/run_integration_tests_windows_x86_64.sh
  • aarch64: scripts/run_integration_tests_windows_aarch64.sh

Both scripts require a pre-downloaded Windows guest image in the workloads directory. Device mapper snapshots are created to allow concurrent test runs without corrupting the base image.

Workloads:

ArchitectureImageFirmware
x86_64windows-server-2025-amd64-1.rawCLOUDHV.fd
aarch64windows-11-iot-enterprise-aarch64.rawCLOUDHV_EFI.fd

Test group: windows (single-threaded, retries 3).

Rate limiter

shell
scripts/dev_cli.sh tests --integration-rate-limiter

Runs scripts/run_integration_tests_rate_limiter.sh. Downloads Jammy guest images and a prebuilt kernel.

Test group: rate_limiter (single-threaded, no retries).

Confidential VMs

shell
scripts/dev_cli.sh tests --integration-cvm [--hypervisor mshv]

Runs scripts/run_integration_tests_cvm.sh. Builds with --features mshv,igvm,sev_snp and requires IGVM files to be present at /usr/share/cloud-hypervisor/cvm on the host.

Test group: common_cvm (nproc / 4 threads, retries 3).

Performance metrics

shell
scripts/dev_cli.sh tests --metrics [-- <script args> [-- <binary args>]]

Runs scripts/run_metrics.sh, which builds and executes the performance-metrics binary. The binary produces a JSON report with boot time, throughput, and latency measurements.

Useful arguments:

shell
# Exclude micro-benchmarks and write results to a file
scripts/dev_cli.sh tests --metrics \
    -- --test-exclude micro_ \
    -- --report-file /root/workloads/metrics.json

Code coverage

shell
scripts/dev_cli.sh tests --coverage

Runs scripts/run_coverage.sh, which instruments the build with LLVM source-based code coverage, executes the test suite via dbus-run-session, and produces either an LCOV or HTML report. See coverage.md for details on collecting and viewing coverage data.