use super::*;
use std::sync::atomic::{AtomicBool, Ordering};
#[test]
fn handle_freeze_drain_swallows_eintr_and_resets_state() {
use crate::vmm::kvm::KtstrKvm;
use crate::vmm::topology::Topology;
let topo = Topology {
llcs: 1,
cores_per_llc: 1,
threads_per_core: 1,
numa_nodes: 1,
nodes: None,
distances: None,
};
let mut vm = KtstrKvm::new(topo, 64, false).unwrap();
crate::vmm::x86_64::boot::setup_sregs(&vm.guest_mem, &vm.vcpus[0], false).unwrap();
let kill = std::sync::Arc::new(AtomicBool::new(false));
let freeze = std::sync::Arc::new(AtomicBool::new(false));
let parked = std::sync::Arc::new(AtomicBool::new(false));
let regs_slot = std::sync::Arc::new(std::sync::Mutex::new(None));
handle_freeze(
&mut vm.vcpus[0],
true, &kill,
&freeze,
&parked,
®s_slot,
None,
None,
None,
);
assert!(
!parked.load(Ordering::Acquire),
"parked must be cleared on exit so subsequent freeze \
cycles can observe a fresh true→false edge"
);
let snapshot = regs_slot.lock().unwrap();
assert!(
snapshot.is_some(),
"capture_vcpu_regs must populate regs_slot for a freshly-\
init'd vCPU — None means KVM_GET_REGS failed unexpectedly"
);
}
#[test]
fn handle_freeze_no_drain_when_immediate_exit_unsupported() {
use crate::vmm::kvm::KtstrKvm;
use crate::vmm::topology::Topology;
let topo = Topology {
llcs: 1,
cores_per_llc: 1,
threads_per_core: 1,
numa_nodes: 1,
nodes: None,
distances: None,
};
let mut vm = KtstrKvm::new(topo, 64, false).unwrap();
crate::vmm::x86_64::boot::setup_sregs(&vm.guest_mem, &vm.vcpus[0], false).unwrap();
let kill = std::sync::Arc::new(AtomicBool::new(false));
let freeze = std::sync::Arc::new(AtomicBool::new(false));
let parked = std::sync::Arc::new(AtomicBool::new(false));
let regs_slot = std::sync::Arc::new(std::sync::Mutex::new(None));
handle_freeze(
&mut vm.vcpus[0],
false, &kill,
&freeze,
&parked,
®s_slot,
None,
None,
None,
);
assert!(!parked.load(Ordering::Acquire));
assert!(regs_slot.lock().unwrap().is_some());
}
#[test]
fn handle_freeze_writes_parked_evt_edge() {
use crate::vmm::kvm::KtstrKvm;
use crate::vmm::topology::Topology;
let topo = Topology {
llcs: 1,
cores_per_llc: 1,
threads_per_core: 1,
numa_nodes: 1,
nodes: None,
distances: None,
};
let mut vm = KtstrKvm::new(topo, 64, false).unwrap();
crate::vmm::x86_64::boot::setup_sregs(&vm.guest_mem, &vm.vcpus[0], false).unwrap();
let kill = std::sync::Arc::new(AtomicBool::new(false));
let freeze = std::sync::Arc::new(AtomicBool::new(false));
let parked = std::sync::Arc::new(AtomicBool::new(false));
let regs_slot = std::sync::Arc::new(std::sync::Mutex::new(None));
let parked_evt = EventFd::new(vmm_sys_util::eventfd::EFD_NONBLOCK).unwrap();
handle_freeze(
&mut vm.vcpus[0],
false,
&kill,
&freeze,
&parked,
®s_slot,
Some(&parked_evt),
None,
None,
);
let counter = parked_evt.read().unwrap();
assert_eq!(
counter, 1,
"handle_freeze must write exactly one wake edge to \
parked_evt — coordinator depends on this to advance \
from epoll_wait without spurious extra wakes"
);
}