Skip to content

Commit 2f6913d

Browse files
committed
test: add Rust integration tests for PCI-enabled uVMs
We have some Rust integration tests that check building and booting of microVMs works correctly. Add variants for PCI-enabled microVMs. Signed-off-by: Babis Chalios <bchalios@amazon.es>
1 parent 7c4179b commit 2f6913d

File tree

2 files changed

+80
-48
lines changed

2 files changed

+80
-48
lines changed

src/vmm/src/test_utils/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub fn create_vmm(
6969
_kernel_image: Option<&str>,
7070
is_diff: bool,
7171
boot_microvm: bool,
72+
pci_enabled: bool,
7273
) -> (Arc<Mutex<Vmm>>, EventManager) {
7374
let mut event_manager = EventManager::new().unwrap();
7475
let empty_seccomp_filters = get_empty_filters();
@@ -82,14 +83,16 @@ pub fn create_vmm(
8283
None => boot_source_cfg.into(),
8384
};
8485
let mock_vm_res = MockVmResources::new().with_boot_source(boot_source_cfg);
85-
let resources: VmResources = if is_diff {
86+
let mut resources: VmResources = if is_diff {
8687
mock_vm_res
8788
.with_vm_config(MockVmConfig::new().with_dirty_page_tracking().into())
8889
.into()
8990
} else {
9091
mock_vm_res.into()
9192
};
9293

94+
resources.pci_enabled = pci_enabled;
95+
9396
let vmm = build_microvm_for_boot(
9497
&InstanceInfo::default(),
9598
&resources,
@@ -106,16 +109,24 @@ pub fn create_vmm(
106109
}
107110

108111
pub fn default_vmm(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
109-
create_vmm(kernel_image, false, true)
112+
create_vmm(kernel_image, false, true, false)
110113
}
111114

112115
pub fn default_vmm_no_boot(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
113-
create_vmm(kernel_image, false, false)
116+
create_vmm(kernel_image, false, false, false)
117+
}
118+
119+
pub fn default_vmm_pci_no_boot(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
120+
create_vmm(kernel_image, false, false, true)
114121
}
115122

116123
#[cfg(target_arch = "x86_64")]
117124
pub fn dirty_tracking_vmm(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
118-
create_vmm(kernel_image, true, true)
125+
create_vmm(kernel_image, true, true, false)
126+
}
127+
128+
pub fn default_vmm_pci(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
129+
create_vmm(kernel_image, false, true, false)
119130
}
120131

121132
#[allow(clippy::undocumented_unsafe_blocks)]

src/vmm/tests/integration_tests.rs

Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use std::io::{Seek, SeekFrom};
5+
use std::sync::{Arc, Mutex};
56
use std::thread;
67
use std::time::Duration;
78

@@ -15,7 +16,9 @@ use vmm::rpc_interface::{
1516
use vmm::seccomp::get_empty_filters;
1617
use vmm::snapshot::Snapshot;
1718
use vmm::test_utils::mock_resources::{MockVmResources, NOISY_KERNEL_IMAGE};
18-
use vmm::test_utils::{create_vmm, default_vmm, default_vmm_no_boot};
19+
use vmm::test_utils::{
20+
create_vmm, default_vmm, default_vmm_no_boot, default_vmm_pci, default_vmm_pci_no_boot,
21+
};
1922
use vmm::vmm_config::balloon::BalloonDeviceConfig;
2023
use vmm::vmm_config::boot_source::BootSourceConfig;
2124
use vmm::vmm_config::drive::BlockDeviceConfig;
@@ -26,9 +29,23 @@ use vmm::vmm_config::snapshot::{
2629
CreateSnapshotParams, LoadSnapshotParams, MemBackendConfig, MemBackendType, SnapshotType,
2730
};
2831
use vmm::vmm_config::vsock::VsockDeviceConfig;
29-
use vmm::{DumpCpuConfigError, EventManager, FcExitCode};
32+
use vmm::{DumpCpuConfigError, EventManager, FcExitCode, Vmm};
3033
use vmm_sys_util::tempfile::TempFile;
3134

35+
fn check_booted_microvm(vmm: Arc<Mutex<Vmm>>, mut evmgr: EventManager) {
36+
// On x86_64, the vmm should exit once its workload completes and signals the exit event.
37+
// On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
38+
#[cfg(target_arch = "x86_64")]
39+
evmgr.run_with_timeout(500).unwrap();
40+
#[cfg(target_arch = "aarch64")]
41+
vmm.lock().unwrap().stop(FcExitCode::Ok);
42+
43+
assert_eq!(
44+
vmm.lock().unwrap().shutdown_exit_code(),
45+
Some(FcExitCode::Ok)
46+
);
47+
}
48+
3249
#[test]
3350
fn test_build_and_boot_microvm() {
3451
// Error case: no boot source configured.
@@ -47,33 +64,24 @@ fn test_build_and_boot_microvm() {
4764
}
4865

4966
// Success case.
50-
let (vmm, mut _evmgr) = default_vmm(None);
67+
let (vmm, evmgr) = default_vmm(None);
68+
check_booted_microvm(vmm, evmgr);
5169

52-
// On x86_64, the vmm should exit once its workload completes and signals the exit event.
53-
// On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
54-
#[cfg(target_arch = "x86_64")]
55-
_evmgr.run_with_timeout(500).unwrap();
56-
#[cfg(target_arch = "aarch64")]
57-
vmm.lock().unwrap().stop(FcExitCode::Ok);
58-
59-
assert_eq!(
60-
vmm.lock().unwrap().shutdown_exit_code(),
61-
Some(FcExitCode::Ok)
62-
);
70+
// microVM with PCI
71+
let (vmm, evmgr) = default_vmm_pci(None);
72+
check_booted_microvm(vmm, evmgr);
6373
}
6474

65-
#[test]
66-
fn test_build_microvm() {
75+
fn check_build_microvm(vmm: Arc<Mutex<Vmm>>, mut evmgr: EventManager) {
6776
// The built microVM should be in the `VmState::Paused` state here.
68-
let (vmm, mut _evtmgr) = default_vmm_no_boot(None);
6977
assert_eq!(vmm.lock().unwrap().instance_info().state, VmState::Paused);
7078

7179
// The microVM should be able to resume and exit successfully.
7280
// On x86_64, the vmm should exit once its workload completes and signals the exit event.
7381
// On aarch64, the test kernel doesn't exit, so the vmm is force-stopped.
7482
vmm.lock().unwrap().resume_vm().unwrap();
7583
#[cfg(target_arch = "x86_64")]
76-
_evtmgr.run_with_timeout(500).unwrap();
84+
evmgr.run_with_timeout(500).unwrap();
7785
#[cfg(target_arch = "aarch64")]
7886
vmm.lock().unwrap().stop(FcExitCode::Ok);
7987
assert_eq!(
@@ -83,10 +91,14 @@ fn test_build_microvm() {
8391
}
8492

8593
#[test]
86-
fn test_pause_resume_microvm() {
87-
// Tests that pausing and resuming a microVM work as expected.
88-
let (vmm, _) = default_vmm(None);
94+
fn test_build_microvm() {
95+
let (vmm, evtmgr) = default_vmm_no_boot(None);
96+
check_build_microvm(vmm, evtmgr);
97+
let (vmm, evtmgr) = default_vmm_pci_no_boot(None);
98+
check_build_microvm(vmm, evtmgr);
99+
}
89100

101+
fn pause_resume_microvm(vmm: Arc<Mutex<Vmm>>) {
90102
let mut api_controller = RuntimeApiController::new(VmResources::default(), vmm.clone());
91103

92104
// There's a race between this thread and the vcpu thread, but this thread
@@ -100,6 +112,17 @@ fn test_pause_resume_microvm() {
100112
vmm.lock().unwrap().stop(FcExitCode::Ok);
101113
}
102114

115+
#[test]
116+
fn test_pause_resume_microvm() {
117+
// Tests that pausing and resuming a microVM work as expected.
118+
let (vmm, _) = default_vmm(None);
119+
120+
pause_resume_microvm(vmm);
121+
122+
let (vmm, _) = default_vmm_pci(None);
123+
pause_resume_microvm(vmm);
124+
}
125+
103126
#[test]
104127
fn test_dirty_bitmap_error() {
105128
// Error case: dirty tracking disabled.
@@ -185,11 +208,11 @@ fn test_disallow_dump_cpu_config_without_pausing() {
185208
vmm.lock().unwrap().stop(FcExitCode::Ok);
186209
}
187210

188-
fn verify_create_snapshot(is_diff: bool) -> (TempFile, TempFile) {
211+
fn verify_create_snapshot(is_diff: bool, pci_enabled: bool) -> (TempFile, TempFile) {
189212
let snapshot_file = TempFile::new().unwrap();
190213
let memory_file = TempFile::new().unwrap();
191214

192-
let (vmm, _) = create_vmm(Some(NOISY_KERNEL_IMAGE), is_diff, true);
215+
let (vmm, _) = create_vmm(Some(NOISY_KERNEL_IMAGE), is_diff, true, pci_enabled);
193216
let resources = VmResources {
194217
machine_config: MachineConfig {
195218
mem_size_mib: 1,
@@ -296,29 +319,27 @@ fn verify_load_snapshot(snapshot_file: TempFile, memory_file: TempFile) {
296319

297320
#[test]
298321
fn test_create_and_load_snapshot() {
299-
// Create diff snapshot.
300-
let (snapshot_file, memory_file) = verify_create_snapshot(true);
301-
// Create a new microVm from snapshot. This only tests code-level logic; it verifies
302-
// that a microVM can be built with no errors from given snapshot.
303-
// It does _not_ verify that the guest is actually restored properly. We're using
304-
// python integration tests for that.
305-
verify_load_snapshot(snapshot_file, memory_file);
306-
307-
// Create full snapshot.
308-
let (snapshot_file, memory_file) = verify_create_snapshot(false);
309-
// Create a new microVm from snapshot. This only tests code-level logic; it verifies
310-
// that a microVM can be built with no errors from given snapshot.
311-
// It does _not_ verify that the guest is actually restored properly. We're using
312-
// python integration tests for that.
313-
verify_load_snapshot(snapshot_file, memory_file);
322+
for (diff_snap, pci_enabled) in [(false, false), (false, true), (true, false), (true, true)] {
323+
// Create snapshot.
324+
let (snapshot_file, memory_file) = verify_create_snapshot(diff_snap, pci_enabled);
325+
// Create a new microVm from snapshot. This only tests code-level logic; it verifies
326+
// that a microVM can be built with no errors from given snapshot.
327+
// It does _not_ verify that the guest is actually restored properly. We're using
328+
// python integration tests for that.
329+
verify_load_snapshot(snapshot_file, memory_file);
330+
}
314331
}
315332

316333
#[test]
317334
fn test_snapshot_load_sanity_checks() {
318-
use vmm::persist::SnapShotStateSanityCheckError;
319-
320-
let mut microvm_state = get_microvm_state_from_snapshot();
335+
let microvm_state = get_microvm_state_from_snapshot(false);
336+
check_snapshot(microvm_state);
337+
let microvm_state = get_microvm_state_from_snapshot(true);
338+
check_snapshot(microvm_state);
339+
}
321340

341+
fn check_snapshot(mut microvm_state: MicrovmState) {
342+
use vmm::persist::SnapShotStateSanityCheckError;
322343
snapshot_state_sanity_check(&microvm_state).unwrap();
323344

324345
// Remove memory regions.
@@ -331,9 +352,9 @@ fn test_snapshot_load_sanity_checks() {
331352
);
332353
}
333354

334-
fn get_microvm_state_from_snapshot() -> MicrovmState {
355+
fn get_microvm_state_from_snapshot(pci_enabled: bool) -> MicrovmState {
335356
// Create a diff snapshot
336-
let (snapshot_file, _) = verify_create_snapshot(true);
357+
let (snapshot_file, _) = verify_create_snapshot(true, pci_enabled);
337358

338359
// Deserialize the microVM state.
339360
let snapshot_file_metadata = snapshot_file.as_file().metadata().unwrap();
@@ -344,7 +365,7 @@ fn get_microvm_state_from_snapshot() -> MicrovmState {
344365
}
345366

346367
fn verify_load_snap_disallowed_after_boot_resources(res: VmmAction, res_name: &str) {
347-
let (snapshot_file, memory_file) = verify_create_snapshot(false);
368+
let (snapshot_file, memory_file) = verify_create_snapshot(false, false);
348369

349370
let mut event_manager = EventManager::new().unwrap();
350371
let empty_seccomp_filters = get_empty_filters();

0 commit comments

Comments
 (0)