docs/testing.md
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.
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.
# Verify KVM is available
ls -l /dev/kvm
The container image bundles all build dependencies. No Rust toolchain is needed on the host.
scripts/dev_cli.sh [flags] <command> [<command args>]
| Flag | Description |
|---|---|
--local | Build and use a local container image instead of pulling from the registry. |
scripts/dev_cli.sh build [--debug|--release] [--libc musl|gnu] \
[--hypervisor kvm|mshv] [--features <features>] \
[--volumes /host:/ctr#...] [-- <cargo args>]
| Flag | Default | Description |
|---|---|---|
--debug | yes | Build debug binaries. |
--release | Build release binaries. | |
--libc | gnu | C library to link against (musl/gnu). |
--hypervisor | kvm | Hypervisor backend (kvm/mshv). |
--features | Additional cargo features. | |
--volumes | Extra host volumes (/a:/a#/b:/b). | |
--runtime | docker | Container runtime (docker/podman). |
Arguments after -- are forwarded directly to cargo build.
scripts/dev_cli.sh tests [<test type>] [--libc musl|gnu] \
[--hypervisor kvm|mshv] [--volumes /host:/ctr#...] \
[-- <script args> [-- <binary args>]]
Test type flags:
| Flag | Description |
|---|---|
--unit | Run unit tests. |
--integration | Run integration tests (includes live migration). |
--integration-vfio | Run VFIO integration tests. |
--integration-windows | Run Windows guest integration tests. |
--integration-rate-limiter | Run rate limiter integration tests. |
--integration-cvm | Run confidential VM integration tests. |
--metrics | Generate performance metrics. |
--coverage | Generate code coverage. |
--all | Run both unit and integration tests. |
Configuration flags:
| Flag | Default | Description |
|---|---|---|
--libc | gnu | C library to link against (musl/gnu). |
--hypervisor | kvm | Hypervisor backend (kvm/mshv). |
--volumes | Extra host volumes (/a:/a#/b:/b). |
The -- separator creates layers of argument forwarding:
dev_cli.sh tests <flags> -- <script args> -- <binary args>
-- is consumed by dev_cli.sh.-- is forwarded to the
test script (e.g., run_integration_tests_x86_64.sh).-- 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:
| Argument | Description |
|---|---|
--hypervisor kvm|mshv | Select 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-kernel | Build the guest kernel from source instead of downloading a prebuilt binary. |
Example — run a single integration test:
scripts/dev_cli.sh tests --integration \
-- --test-filter test_boot_from_virtio_pmem
Example — run metrics excluding micro-benchmarks:
scripts/dev_cli.sh tests --metrics \
-- --test-exclude micro_ \
-- --report-file /root/workloads/metrics.json
The following environment variables allow overriding the default guest kernel or firmware binaries. Each variable is independent; set any combination without affecting the others.
| Variable | Description |
|---|---|
CH_CUSTOM_KERNEL | Path to a custom vmlinux (x86_64) or Image (aarch64) kernel binary. |
CH_CUSTOM_FIRMWARE | Path to a custom hypervisor-fw firmware binary. |
CH_CUSTOM_OVMF | Path 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.
# 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
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).
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:
| Module | Description |
|---|---|
common_parallel | Main tests run in parallel, including live migration. |
common_sequential | Tests requiring serial execution (snapshot/restore, OVS-DPDK live migration). |
dbus_api | D-Bus API tests (requires dbus_api feature). |
fw_cfg | Firmware configuration tests (requires fw_cfg feature). |
ivshmem | Inter-VM shared memory tests (requires ivshmem feature). |
aarch64_acpi | ARM64 ACPI-specific tests. |
windows | Windows guest tests. |
vfio | VFIO passthrough tests (x86_64 only). |
rate_limiter | Network/block rate limiting tests. |
Confidential VM tests are in a separate file
(cloud-hypervisor/tests/integration_cvm.rs) under the common_cvm
module.
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:
vmlinux-x86_64 (prebuilt or built from source with
--build-guest-kernel).hypervisor-fw (rust-hypervisor-firmware).CLOUDHV.fd.System tuning applied inside the container:
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.
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:
Image-arm64.CLOUDHV_EFI.fd.Test groups executed: common_parallel, common_sequential,
aarch64_acpi, dbus_api, fw_cfg, ivshmem.
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):
| Group | Description |
|---|---|
vfio::test_nvidia | Legacy VFIO with container/group interface. |
vfio::test_iommufd | VFIO with cdev interface via iommufd. |
scripts/dev_cli.sh tests --integration-windows [--libc musl|gnu]
Runs the architecture-appropriate script:
scripts/run_integration_tests_windows_x86_64.shscripts/run_integration_tests_windows_aarch64.shBoth 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:
| Architecture | Image | Firmware |
|---|---|---|
| x86_64 | windows-server-2025-amd64-1.raw | CLOUDHV.fd |
| aarch64 | windows-11-iot-enterprise-aarch64.raw | CLOUDHV_EFI.fd |
Test group: windows (single-threaded, retries 3).
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).
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).
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:
# Exclude micro-benchmarks and write results to a file
scripts/dev_cli.sh tests --metrics \
-- --test-exclude micro_ \
-- --report-file /root/workloads/metrics.json
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.