microsoft/openvmm

Public

mirrored from https://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fe2bbc9829558a07c5e06d2b6ececc383b6593bf

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Guide/src/dev_guide/tests/vmm.md

254lines · modecode

1# VMM Tests
2
3The OpenVMM repo contains a set of "heavyweight" VMM tests that fully boot a
4virtual machine and run validation against it. Unlike Unit tests, these are all
5centralized in a single top-level `vmm_tests` directory.
6
7The OpenVMM PR and CI pipelines will run the full test suite on all supported
8platforms; you'd typically run only the tests relevant to the changes you're
9working on.
10
11## Writing VMM Tests
12
13To streamline the process of booting and interacting with VMs during VMM tests, the
14OpenVMM project uses an in-house test framework/library called `petri`.
15
16The library does not yet have a stable API, so at this time, the best way to
17learn how to write new VMM tests is by reading through the existing corpus of
18tests (start with vmm_tests/vmm_tests/tests/tests/multiarch.rs),
19as well as reading through `petri`'s rustdoc-generated API docs.
20
21The tests are currently generated using a macro (`#[vmm_test]`) that allows
22the same test body to be run in a variety of scenarios, with different guest
23operating systems, firmwares, and VMMs (including Hyper-V, which is useful
24for testing certain OpenHCL features that aren't supported when using
25OpenVMM as the host VMM).
26
27### "heavy" tests
28
29The global [nextest.toml](https://github.com/microsoft/openvmm/blob/main/.config/nextest.toml)
30configures how tests run in our test environments. The `default` and `ci` profiles
31control things like timeouts, and how many resources we allocate to a given test. The number
32of required threads is a fuzzy requirement relative to the number of VPs consumed by the VM under
33test, the amount of memory your test needs, the host test framework (petri itself), and so on.
34
35We have some pre-defined overrides that perform filterset matching on test name. These overrides
36are curated to balance individual trial (test case) performance against overall concurrency on
37engineers' local machines and in CI. Put these special words in your test to opt in to that override:
38
39- `heavy` - if your test is heavier than the typical vmm_test. E.g., your test explicitly requests 16 virtual processors.
40- `very_heavy` if your test is heavier than a `heavy` test. E.g., your test explicitly requests 32 virtual processors.
41
42### "unstable" tests
43
44If a test is not yet reliable enough to gate PRs, add `unstable` to the macro.
45
46For individual variants:
47
48```rust,ignore
49#[vmm_test(
50 // unstable variant:
51 unstable_hyperv_openhcl_uefi_aarch64(vhd(windows_11_enterprise_aarch64)),
52 // other reliable variants:
53 hyperv_openhcl_uefi_aarch64(vhd(ubuntu_2404_server_aarch64))
54 // ...
55)]
56async fn my_test<T: PetriVmmBackend>(config: PetriVmBuilder<T>) -> anyhow::Result<()> {
57 // ...
58}
59```
60
61For all variants of the test:
62
63```rust,ignore
64#[vmm_test_with(unstable(
65 hyperv_openhcl_uefi_aarch64(vhd(windows_11_enterprise_aarch64)),
66 hyperv_openhcl_uefi_aarch64(vhd(ubuntu_2404_server_aarch64))
67 // ...
68))]
69async fn my_test<T: PetriVmmBackend>(config: PetriVmBuilder<T>) -> anyhow::Result<()> {
70 // ...
71}
72```
73
74Unstable tests run in the same CI job as stable tests. When an unstable test fails
75the CI run will pass with a warning
76
77To promote an unstable test to stable, remove `unstable` from the macro. This is
78a single-place change — no CI or configuration updates are required.
79
80To ignore these `unstable` tags and report failures for all tests when running
81locally, set the following environment variable: `PETRI_REPORT_UNSTABLE_FAIL=1`
82
83## Running VMM Tests (Flowey)
84
85The easiest way to run VMM tests locally is `cargo xflowey vmm-tests-run`. It
86automatically discovers required artifacts, builds dependencies, and runs your
87tests in a single command.
88
89To run a **specific test** (or set of tests), use `--filter` with a
90[nextest filter](https://nexte.st/docs/filtersets/) expression:
91
92```bash
93cargo xflowey vmm-tests-run --filter "test(my_test_name)" --dir /tmp/vmm-tests-run
94```
95
96### Targeting a Platform
97
98By default, `vmm-tests-run` builds for the current host. Use `--target` to
99build for a different platform. The supported targets are:
100
101| Target | Description |
102|--------|-------------|
103| `windows-x64` | Windows x86_64 (Hyper-V / WHP) |
104| `windows-aarch64` | Windows ARM64 (Hyper-V / WHP) |
105| `linux-x64` | Linux x86_64 |
106
107**Cross-compiling for Windows from WSL2** is fully supported, you can build
108and run Windows VMM tests directly from your WSL2 shell. This requires the
109cross-compilation environment to be set up first.
110
111Then target Windows as usual. The output directory **must** be on the Windows
112filesystem (e.g., `/mnt/d/...`):
113
114```bash
115cargo xflowey vmm-tests-run --target windows-x64 --dir /mnt/d/vmm_tests
116```
117
118For full cross-compilation setup instructions, see
119[Cross Compiling for Windows](../getting_started/cross_compile.md).
120
121When running Hyper-V tests, your user account must be a member of the
122Hyper-V Administrators group.
123
124To see all available options: `cargo xflowey vmm-tests-run --help`.
125
126### Lazy Fetch (Default)
127
128By default, VHD/ISO disk images are streamed on demand via HTTP and cached
129locally in a SQLite database. This avoids multi-GB upfront downloads and
130significantly speeds up the dev inner loop once the cache is warm.
131
132Lazy fetch is automatically disabled for Hyper-V tests, which require local
133files. To force all images to be downloaded upfront, pass `--no-lazy-fetch`:
134
135```bash
136cargo xflowey vmm-tests-run --filter "test(my_test)" --dir /tmp/vmm-tests-run --no-lazy-fetch
137```
138
139## Running VMM Tests (Manual)
140
141```admonish tip
142Note: We recommend using [cargo-nextest](https://nexte.st/) to run unit / VMM
143tests. It is a significant improvement over the built-in `cargo test` runner,
144and is the test runner we use in all our CI pipelines.
145
146You can install it locally by running: `cargo install cargo-nextest --locked`
147
148See the [cargo-nextest](https://nexte.st/) documentation for more info.
149```
150
151You can directly invoke `cargo test` or `cargo nextest` to run the vmm
152tests manually.
153
154Unlike Unit Tests, VMM tests may rely on additional external artifacts in order
155to run. e.g: Virtual Disk Images, pre-built OpenHCL binaries, UEFI / PCAT
156firmware blobs, etc.
157
158As such, the first step in running a VMM test is to ensure you have acquired all
159external test artifacts it may depend upon.
160
161The VMM test infrastructure does not automatically fetch / rebuild
162necessary artifacts unless you are using [flowey](#running-vmm-tests-flowey).
163However, the test infrastructure is designed to report clear
164and actionable error messages whenever a required test artifact cannot be found,
165which provide detailed instructions on how to build / acquire the missing
166artifact. Some dependencies can only be built on Linux (OpenHCL and Linux
167pipette, for example). If you are building on Linux and want to run Windows
168guest tests, pipette will need to be
169[cross compiled for Windows](#linux-cross-compiling-pipetteexe).
170
171```admonish warning
172`cargo nextest run` won't rebuild any of your changes. Make sure you `cargo build`
173or `cargo xflowey igvm [RECIPE]` first!
174```
175
176VMM tests are run using standard Rust test infrastructure, and are invoked via
177`cargo test` / `cargo nextest`.
178
179```bash
180cargo nextest run -p vmm_tests [TEST_FILTERS]
181```
182
183For example, to run a simple VMM test that simply boots using UEFI:
184
185```bash
186cargo nextest run -p vmm_tests multiarch::openvmm_uefi_x64_frontpage
187```
188
189And, for further example, to rebuild everything* and run all* the tests
190(see below for details on these steps):
191
192*This will not work for Hyper-V tests. TMK tests need additional build steps.
193
194```bash
195# Install (most) of the dependencies; cargo nextest run may tell you
196# about other deps.
197rustup target add x86_64-unknown-none
198rustup target add x86_64-unknown-uefi
199rustup target add x86_64-pc-windows-msvc
200sudo apt install clang-tools-14 lld-14
201
202cargo install cargo-nextest --locked
203
204cargo xtask guest-test download-image
205cargo xtask guest-test uefi --bootx64
206
207# Rebuild all, and run all tests
208cargo build --target x86_64-pc-windows-msvc -p pipette
209cargo build --target x86_64-unknown-linux-musl -p pipette
210
211cargo build --target x86_64-pc-windows-msvc -p openvmm
212
213cargo xflowey build-igvm x64-test-linux-direct
214cargo xflowey build-igvm x64-cvm
215cargo xflowey build-igvm x64
216
217cargo nextest run --target x86_64-pc-windows-msvc -p vmm_tests --filter-expr 'all() & !test(hyperv) & !test(tmk)'
218```
219
220### \[Linux] Cross-compiling `pipette.exe`
221
222These commands might use the test agent (`pipette`) that is put inside the VM,
223and if the host machine OS and the guest machine OS are different, a setup
224is required for cross-building. The recommended approach is to use WSL2 and
225cross-compile using the freely available Microsoft Visual Studio Build Tools
226or Microsoft Visual Studio Community Edition as described in
227[\[WSL2\] Cross Compiling from WSL2 to Windows](../getting_started/cross_compile.md)
228
229If that is not possible, here is another option that relies on [MinGW-w64](https://www.mingw-w64.org/)
230and doesn't require installing Windows:
231
232```bash
233# Do 1 once, do 2 as needed.
234#
235# 1. Setup the toolchain
236rustup target add x86_64-pc-windows-gnu
237sudo apt-get install mingw-w64-x86-64-dev
238mingw-genlib -a x86_64 ./support/pal/api-ms-win-security-base-private-l1-1-1.def
239sudo mv libapi-ms-win-security-base-private-l1-1-1.a /usr/x86_64-w64-mingw32/lib
240
241# 2. Build Pipette (builds target/x86_64-pc-windows-gnu/debug/pipette.exe first)
242cargo build --target x86_64-pc-windows-gnu -p pipette
243```
244
245```bash
246# Run a test
247cargo nextest run -p vmm_tests multiarch::openvmm_uefi_x64_windows_datacenter_core_2022_x64_boot
248```
249
250### Printing logs for VMM Tests
251
252In order to see the OpenVMM logs while running a VMM test, do the following:
2531. Add the `--no-capture` flag to your `cargo nextest` command.
2542. Set `OPENVMM_LOG=trace`, replacing `trace` with the log level you want to view.