mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-31 03:17:01 +00:00
Merge pull request #5611 from wllenyj/dragonball-ut-4
Built-in Sandbox: add more unit tests for dragonball. Part 4
This commit is contained in:
commit
1b46d4fb50
@ -228,7 +228,7 @@ mod tests {
|
|||||||
assert!(c.max_memslots >= 32);
|
assert!(c.max_memslots >= 32);
|
||||||
|
|
||||||
let kvm = Kvm::new().unwrap();
|
let kvm = Kvm::new().unwrap();
|
||||||
let f = unsafe { File::from_raw_fd(kvm.as_raw_fd()) };
|
let f = std::mem::ManuallyDrop::new(unsafe { File::from_raw_fd(kvm.as_raw_fd()) });
|
||||||
let m1 = f.metadata().unwrap();
|
let m1 = f.metadata().unwrap();
|
||||||
let m2 = File::open("/dev/kvm").unwrap().metadata().unwrap();
|
let m2 = File::open("/dev/kvm").unwrap().metadata().unwrap();
|
||||||
|
|
||||||
|
@ -758,13 +758,11 @@ impl Drop for Vcpu {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use dbs_device::device_manager::IoManager;
|
use dbs_device::device_manager::IoManager;
|
||||||
use kvm_ioctls::Kvm;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use test_utils::skip_if_not_root;
|
use test_utils::skip_if_not_root;
|
||||||
|
|
||||||
@ -812,12 +810,8 @@ pub mod tests {
|
|||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn create_vcpu() -> (Vcpu, Receiver<VcpuStateEvent>) {
|
fn create_vcpu() -> (Vcpu, Receiver<VcpuStateEvent>) {
|
||||||
// Call for kvm too frequently would cause error in some host kernel.
|
let kvm_context = KvmContext::new(None).unwrap();
|
||||||
std::thread::sleep(std::time::Duration::from_millis(5));
|
let vm = kvm_context.kvm().create_vm().unwrap();
|
||||||
|
|
||||||
let kvm = Kvm::new().unwrap();
|
|
||||||
let vm = Arc::new(kvm.create_vm().unwrap());
|
|
||||||
let kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap();
|
|
||||||
let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap());
|
let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap());
|
||||||
let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new()))));
|
let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new()))));
|
||||||
let supported_cpuid = kvm_context
|
let supported_cpuid = kvm_context
|
||||||
|
@ -1041,3 +1041,376 @@ impl MutEventSubscriber for VcpuEpollHandler {
|
|||||||
ops.add(Events::new(&self.eventfd, EventSet::IN)).unwrap();
|
ops.add(Events::new(&self.eventfd, EventSet::IN)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use dbs_utils::epoll_manager::EpollManager;
|
||||||
|
#[cfg(feature = "hotplug")]
|
||||||
|
use dbs_virtio_devices::vsock::backend::VsockInnerBackend;
|
||||||
|
use seccompiler::BpfProgram;
|
||||||
|
use test_utils::skip_if_not_root;
|
||||||
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::api::v1::InstanceInfo;
|
||||||
|
use crate::vcpu::vcpu_impl::tests::{EmulationCase, EMULATE_RES};
|
||||||
|
use crate::vm::{CpuTopology, Vm, VmConfigInfo};
|
||||||
|
|
||||||
|
fn get_vm() -> Vm {
|
||||||
|
let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
|
||||||
|
let epoll_manager = EpollManager::default();
|
||||||
|
let mut vm = Vm::new(None, instance_info, epoll_manager).unwrap();
|
||||||
|
let vm_config = VmConfigInfo {
|
||||||
|
vcpu_count: 1,
|
||||||
|
max_vcpu_count: 3,
|
||||||
|
cpu_pm: "off".to_string(),
|
||||||
|
mem_type: "shmem".to_string(),
|
||||||
|
mem_file_path: "".to_string(),
|
||||||
|
mem_size_mib: 100,
|
||||||
|
serial_path: None,
|
||||||
|
cpu_topology: CpuTopology {
|
||||||
|
threads_per_core: 1,
|
||||||
|
cores_per_die: 3,
|
||||||
|
dies_per_socket: 1,
|
||||||
|
sockets: 1,
|
||||||
|
},
|
||||||
|
vpmu_feature: 0,
|
||||||
|
};
|
||||||
|
vm.set_vm_config(vm_config);
|
||||||
|
vm.init_guest_memory().unwrap();
|
||||||
|
|
||||||
|
vm.init_vcpu_manager(vm.vm_as().unwrap().clone(), BpfProgram::default())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
vm.vcpu_manager()
|
||||||
|
.unwrap()
|
||||||
|
.set_reset_event_fd(EventFd::new(libc::EFD_NONBLOCK).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
|
{
|
||||||
|
vm.setup_interrupt_controller().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
vm
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_present_unstart_vcpus(vcpu_manager: &std::sync::MutexGuard<'_, VcpuManager>) -> u8 {
|
||||||
|
vcpu_manager
|
||||||
|
.vcpu_infos
|
||||||
|
.iter()
|
||||||
|
.fold(0, |sum, info| sum + info.vcpu.is_some() as u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_config() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
|
||||||
|
let epoll_manager = EpollManager::default();
|
||||||
|
let mut vm = Vm::new(None, instance_info, epoll_manager).unwrap();
|
||||||
|
let vm_config = VmConfigInfo {
|
||||||
|
vcpu_count: 1,
|
||||||
|
max_vcpu_count: 2,
|
||||||
|
cpu_pm: "off".to_string(),
|
||||||
|
mem_type: "shmem".to_string(),
|
||||||
|
mem_file_path: "".to_string(),
|
||||||
|
mem_size_mib: 1,
|
||||||
|
serial_path: None,
|
||||||
|
cpu_topology: CpuTopology {
|
||||||
|
threads_per_core: 1,
|
||||||
|
cores_per_die: 2,
|
||||||
|
dies_per_socket: 1,
|
||||||
|
sockets: 1,
|
||||||
|
},
|
||||||
|
vpmu_feature: 0,
|
||||||
|
};
|
||||||
|
vm.set_vm_config(vm_config.clone());
|
||||||
|
vm.init_guest_memory().unwrap();
|
||||||
|
|
||||||
|
vm.init_vcpu_manager(vm.vm_as().unwrap().clone(), BpfProgram::default())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
// test the vcpu_config
|
||||||
|
assert_eq!(
|
||||||
|
vcpu_manager.vcpu_infos.len(),
|
||||||
|
vm_config.max_vcpu_count as usize
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
vcpu_manager.vcpu_config.boot_vcpu_count,
|
||||||
|
vm_config.vcpu_count
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
vcpu_manager.vcpu_config.max_vcpu_count,
|
||||||
|
vm_config.max_vcpu_count
|
||||||
|
);
|
||||||
|
|
||||||
|
let reset_event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
|
||||||
|
let reset_event_fd_raw = reset_event_fd.as_raw_fd();
|
||||||
|
vcpu_manager.set_reset_event_fd(reset_event_fd).unwrap();
|
||||||
|
|
||||||
|
// test the reset_event_fd
|
||||||
|
assert_eq!(
|
||||||
|
vcpu_manager.reset_event_fd.as_ref().unwrap().as_raw_fd(),
|
||||||
|
reset_event_fd_raw
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_boot_vcpus() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
// test create boot vcpu
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
// test start boot vcpus
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_operate_vcpus() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
// test create vcpu more than max
|
||||||
|
let res = vcpu_manager.create_vcpus(20, None, None);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::ExpectedVcpuExceedMax)));
|
||||||
|
|
||||||
|
// test create vcpus
|
||||||
|
assert!(vcpu_manager.create_vcpus(2, None, None).is_ok());
|
||||||
|
assert_eq!(vcpu_manager.present_vcpus_count(), 0);
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 2);
|
||||||
|
assert_eq!(vcpu_manager.vcpus().len(), 2);
|
||||||
|
assert_eq!(vcpu_manager.vcpus_mut().len(), 2);
|
||||||
|
|
||||||
|
// test start vcpus
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.start_vcpus(1, BpfProgram::default(), false)
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(vcpu_manager.present_vcpus_count(), 1);
|
||||||
|
assert_eq!(vcpu_manager.present_vcpus(), vec![0]);
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.start_vcpus(2, BpfProgram::default(), false)
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(vcpu_manager.present_vcpus_count(), 2);
|
||||||
|
assert_eq!(vcpu_manager.present_vcpus(), vec![0, 1]);
|
||||||
|
|
||||||
|
// test start vcpus more than created
|
||||||
|
let res = vcpu_manager.start_vcpus(3, BpfProgram::default(), false);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::VcpuNotCreate)));
|
||||||
|
|
||||||
|
// test start vcpus less than started
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.start_vcpus(1, BpfProgram::default(), false)
|
||||||
|
.is_ok());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_pause_resume_vcpus() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
*(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
|
||||||
|
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// invalid cpuid for pause
|
||||||
|
let cpu_indexes = vec![2];
|
||||||
|
let res = vcpu_manager.pause_vcpus(&cpu_indexes);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
|
||||||
|
|
||||||
|
// pause success
|
||||||
|
let cpu_indexes = vec![0];
|
||||||
|
assert!(vcpu_manager.pause_vcpus(&cpu_indexes).is_ok());
|
||||||
|
|
||||||
|
// invalid cpuid for resume
|
||||||
|
let cpu_indexes = vec![2];
|
||||||
|
let res = vcpu_manager.resume_vcpus(&cpu_indexes);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
|
||||||
|
|
||||||
|
// success resume
|
||||||
|
let cpu_indexes = vec![0];
|
||||||
|
assert!(vcpu_manager.resume_vcpus(&cpu_indexes).is_ok());
|
||||||
|
|
||||||
|
// pause and resume all
|
||||||
|
assert!(vcpu_manager.pause_all_vcpus().is_ok());
|
||||||
|
assert!(vcpu_manager.resume_all_vcpus().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_exit_vcpus() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
*(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
|
||||||
|
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// invalid cpuid for exit
|
||||||
|
let cpu_indexes = vec![2];
|
||||||
|
|
||||||
|
let res = vcpu_manager.exit_vcpus(&cpu_indexes);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
|
||||||
|
|
||||||
|
// exit success
|
||||||
|
let cpu_indexes = vec![0];
|
||||||
|
assert!(vcpu_manager.exit_vcpus(&cpu_indexes).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_exit_all_vcpus() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
*(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
|
||||||
|
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// exit all success
|
||||||
|
assert!(vcpu_manager.exit_all_vcpus().is_ok());
|
||||||
|
assert_eq!(vcpu_manager.vcpu_infos.len(), 0);
|
||||||
|
assert!(vcpu_manager.io_manager.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_revalidate_vcpus_cache() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
*(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
|
||||||
|
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// invalid cpuid for exit
|
||||||
|
let cpu_indexes = vec![2];
|
||||||
|
|
||||||
|
let res = vcpu_manager.revalidate_vcpus_cache(&cpu_indexes);
|
||||||
|
assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
|
||||||
|
|
||||||
|
// revalidate success
|
||||||
|
let cpu_indexes = vec![0];
|
||||||
|
assert!(vcpu_manager.revalidate_vcpus_cache(&cpu_indexes).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vcpu_manager_revalidate_all_vcpus_cache() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
*(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
|
||||||
|
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// revalidate all success
|
||||||
|
assert!(vcpu_manager.revalidate_all_vcpus_cache().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "hotplug")]
|
||||||
|
fn test_vcpu_manager_resize_cpu() {
|
||||||
|
skip_if_not_root!();
|
||||||
|
let vm = get_vm();
|
||||||
|
let mut vcpu_manager = vm.vcpu_manager().unwrap();
|
||||||
|
|
||||||
|
assert!(vcpu_manager
|
||||||
|
.create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
|
||||||
|
.is_ok());
|
||||||
|
assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
|
||||||
|
|
||||||
|
assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
|
||||||
|
|
||||||
|
// set vcpus in hotplug action
|
||||||
|
let cpu_ids = vec![0];
|
||||||
|
vcpu_manager.set_vcpus_action(VcpuAction::Hotplug, cpu_ids);
|
||||||
|
|
||||||
|
// vcpu is already in hotplug process
|
||||||
|
let res = vcpu_manager.resize_vcpu(1, None);
|
||||||
|
assert!(matches!(
|
||||||
|
res,
|
||||||
|
Err(VcpuManagerError::VcpuResize(
|
||||||
|
VcpuResizeError::VcpuIsHotplugging
|
||||||
|
))
|
||||||
|
));
|
||||||
|
|
||||||
|
// clear vcpus action
|
||||||
|
let cpu_ids = vec![0];
|
||||||
|
vcpu_manager.set_vcpus_action(VcpuAction::None, cpu_ids);
|
||||||
|
|
||||||
|
// no upcall channel
|
||||||
|
let res = vcpu_manager.resize_vcpu(1, None);
|
||||||
|
assert!(matches!(
|
||||||
|
res,
|
||||||
|
Err(VcpuManagerError::VcpuResize(
|
||||||
|
VcpuResizeError::UpdateNotAllowedPostBoot
|
||||||
|
))
|
||||||
|
));
|
||||||
|
|
||||||
|
// init upcall channel
|
||||||
|
let dev_mgr_service = DevMgrService {};
|
||||||
|
let vsock_backend = VsockInnerBackend::new().unwrap();
|
||||||
|
let connector = vsock_backend.get_connector();
|
||||||
|
let epoll_manager = EpollManager::default();
|
||||||
|
let mut upcall_client =
|
||||||
|
UpcallClient::new(connector, epoll_manager, dev_mgr_service).unwrap();
|
||||||
|
assert!(upcall_client.connect().is_ok());
|
||||||
|
vcpu_manager.set_upcall_channel(Some(Arc::new(upcall_client)));
|
||||||
|
|
||||||
|
// success: no need to resize
|
||||||
|
vcpu_manager.resize_vcpu(1, None).unwrap();
|
||||||
|
|
||||||
|
// exceeed max vcpu count
|
||||||
|
let res = vcpu_manager.resize_vcpu(4, None);
|
||||||
|
assert!(matches!(
|
||||||
|
res,
|
||||||
|
Err(VcpuManagerError::VcpuResize(
|
||||||
|
VcpuResizeError::ExpectedVcpuExceedMax
|
||||||
|
))
|
||||||
|
));
|
||||||
|
|
||||||
|
// remove vcpu 0
|
||||||
|
let res = vcpu_manager.resize_vcpu(0, None);
|
||||||
|
assert!(matches!(
|
||||||
|
res,
|
||||||
|
Err(VcpuManagerError::VcpuResize(
|
||||||
|
VcpuResizeError::Vcpu0CanNotBeRemoved
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user