@@ -377,7 +377,7 @@ impl<T: KVMIntrospectable> Drop for Kvm<T> {
377377 }
378378}
379379
380- #[ cfg( test) ]
380+ /* #[cfg(test)]
381381mod tests {
382382 use super::*;
383383 use kvmi::{kvm_regs, kvm_sregs, KvmMsrs};
@@ -386,31 +386,62 @@ mod tests {
386386 use std::fmt::{Debug, Formatter};
387387 use test_case::test_case;
388388
389- #[ test]
390- fn test_fail_to_create_kvm_driver_if_kvmi_init_returns_error ( ) {
391- let mut kvmi_mock = MockKVMi :: default ( ) ;
392- kvmi_mock. expect_init ( ) . returning ( |_| {
393- Err ( std:: io:: Error :: new (
394- std:: io:: ErrorKind :: Other ,
395- "something went wrong" ,
396- ) )
397- } ) ;
398389
399- let result = Kvm :: new (
400- "some_vm" ,
401- kvmi_mock,
402- Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
403- ) ;
404390
405- assert ! ( result . is_err ( ) , "Expected error, got ok instead!" ) ;
406- }
391+
392+
407393
408394 #[test_case(1; "single vcpu")]
409395 #[test_case(2; "two vcpus")]
410396 #[test_case(16; "sixteen vcpus")]
411- fn test_create_kvm_driver_if_guest_domain_is_valid ( vcpu_count : u32 ) {
412- let mut kvmi_mock = MockKVMi :: default ( ) ;
413- kvmi_mock. expect_init ( ) . returning ( |_| Ok ( ( ) ) ) ;
397+
398+
399+ #[test_case(1; "single vcpu")]
400+ #[test_case(2; "two vcpus")]
401+ #[test_case(16; "sixteen vcpus")]
402+
403+
404+ mock! {
405+ KVMi{}
406+ trait Debug {
407+ fn fmt<'a>(&self, f: &mut Formatter<'a>) -> std::fmt::Result;
408+ }
409+ trait KVMIntrospectable: Debug {
410+ fn init(&mut self, socket_path: &str) -> Result<(), std::io::Error>;
411+ fn control_events(
412+ &self,
413+ vcpu: u16,
414+ intercept_type: KVMiInterceptType,
415+ enabled: bool,
416+ ) -> Result<(), std::io::Error>;
417+ fn control_cr(&self, vcpu: u16, reg: KVMiCr, enabled: bool) -> Result<(), std::io::Error>;
418+ fn control_msr(&self, vcpu: u16, reg: u32, enabled: bool) -> Result<(), std::io::Error>;
419+ fn read_physical(&self, gpa: u64, buffer: &mut [u8]) -> Result<(), std::io::Error>;
420+ fn write_physical(&self, gpa: u64, buffer: &[u8]) -> Result<(), std::io::Error>;
421+ fn get_page_access(&self, gpa: u64) -> Result<KVMiPageAccess, std::io::Error>;
422+ fn set_page_access(&self, gpa: u64, access: KVMiPageAccess) -> Result<(), std::io::Error>;
423+ fn pause(&self) -> Result<(), std::io::Error>;
424+ fn get_vcpu_count(&self) -> Result<u32, std::io::Error>;
425+ fn get_registers(&self, vcpu: u16) -> Result<(kvm_regs, kvm_sregs, KvmMsrs), std::io::Error>;
426+ fn set_registers(&self, vcpu: u16, regs: &kvm_regs) -> Result<(), std::io::Error>;
427+ fn wait_and_pop_event(&self, ms: i32) -> Result<Option<KVMiEvent>, std::io::Error>;
428+ fn reply(&self, event: &KVMiEvent, reply_type: KVMiEventReply) -> Result<(), std::io::Error>;
429+ fn get_maximum_gfn(&self) -> Result<u64, std::io::Error>;
430+ }
431+ }
432+ }*/
433+
434+ #[ cfg( test) ]
435+ mod tests {
436+ use super :: * ;
437+ use kvmi:: { kvm_regs, kvm_sregs, KvmMsrs } ;
438+ use mockall:: mock;
439+ use mockall:: predicate:: { eq, function} ;
440+ use std:: fmt:: { Debug , Formatter } ;
441+ use test_case:: test_case;
442+
443+ fn setup_mock ( kvmi_mock : & mut MockKVMi , vcpu_count : u32 ) {
444+ kvmi_mock. expect_init ( ) . times ( 1 ) . returning ( |_| Ok ( ( ) ) ) ;
414445 kvmi_mock
415446 . expect_get_vcpu_count ( )
416447 . returning ( move || Ok ( vcpu_count) ) ;
@@ -488,7 +519,33 @@ mod tests {
488519 . times ( 1 )
489520 . returning ( |_, _, _| Ok ( ( ) ) ) ;
490521 }
522+ }
523+
524+ #[ test]
525+ fn test_fail_to_create_kvm_driver_if_kvmi_init_returns_error ( ) {
526+ let mut kvmi_mock = MockKVMi :: default ( ) ;
527+ kvmi_mock. expect_init ( ) . returning ( |_| {
528+ Err ( std:: io:: Error :: new (
529+ std:: io:: ErrorKind :: Other ,
530+ "something went wrong" ,
531+ ) )
532+ } ) ;
533+
534+ let result = Kvm :: new (
535+ "some_vm" ,
536+ kvmi_mock,
537+ Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
538+ ) ;
539+
540+ assert ! ( result. is_err( ) , "Expected error, got ok instead!" ) ;
541+ }
491542
543+ #[ test_case( 1 ; "single vcpu" ) ]
544+ #[ test_case( 2 ; "two vcpus" ) ]
545+ #[ test_case( 16 ; "sixteen vcpus" ) ]
546+ fn test_create_kvm_driver_if_guest_domain_is_valid ( vcpu_count : u32 ) {
547+ let mut kvmi_mock = MockKVMi :: default ( ) ;
548+ setup_mock ( & mut kvmi_mock, vcpu_count) ;
492549 let result = Kvm :: new (
493550 "some_vm" ,
494551 kvmi_mock,
@@ -498,6 +555,130 @@ mod tests {
498555 assert ! ( result. is_ok( ) , "Expected ok, got error instead!" ) ;
499556 }
500557
558+ #[ test_case( 1 ; "single vcpu" ) ]
559+ fn test_pause_vcpu ( vcpu_count : u32 ) {
560+ let mut kvmi_mock = MockKVMi :: default ( ) ;
561+ setup_mock ( & mut kvmi_mock, vcpu_count) ;
562+ kvmi_mock. expect_pause ( ) . times ( 1 ) . returning ( || Ok ( ( ) ) ) ;
563+ let mut kvm = Kvm :: new (
564+ "some_vm" ,
565+ kvmi_mock,
566+ Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
567+ )
568+ . expect ( "Failed to create driver" ) ;
569+ let result = Kvm :: pause ( & mut kvm) ;
570+ assert ! ( result. is_ok( ) , "Expected ok, got error instead!" ) ;
571+ }
572+
573+ #[ test_case( 1 ; "single vcpu" ) ]
574+ fn test_resume_vcpu ( vcpu_count : u32 ) {
575+ let mut kvmi_mock = MockKVMi :: default ( ) ;
576+ setup_mock ( & mut kvmi_mock, vcpu_count) ;
577+ kvmi_mock
578+ . expect_wait_and_pop_event ( )
579+ . times ( 5 )
580+ . returning ( |_| {
581+ Ok ( Some ( KVMiEvent {
582+ vcpu : 0 ,
583+ ev_type : KVMiEventType :: PauseVCPU ,
584+ ffi_event : std:: ptr:: null_mut ( ) ,
585+ } ) )
586+ } ) ;
587+ kvmi_mock. expect_reply ( ) . times ( 5 ) . returning ( |_, _| Ok ( ( ) ) ) ;
588+ let mut kvm = Kvm :: new (
589+ "some_vm" ,
590+ kvmi_mock,
591+ Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
592+ )
593+ . expect ( "Failed to create driver" ) ;
594+ kvm. expect_pause_ev = 5 ;
595+ let result = Kvm :: resume ( & mut kvm) ;
596+ assert ! ( result. is_ok( ) , "Expected ok, got error instead!" ) ;
597+ }
598+
599+ #[ test_case( 1 ; "single vcpu" ) ]
600+ fn test_read_and_write_physical ( vcpu_count : u32 ) {
601+ let mut kvmi_mock = MockKVMi :: default ( ) ;
602+ setup_mock ( & mut kvmi_mock, vcpu_count) ;
603+ kvmi_mock
604+ . expect_read_physical ( )
605+ . times ( 1 )
606+ . returning ( |_, _| Ok ( ( ) ) ) ;
607+ kvmi_mock
608+ . expect_write_physical ( )
609+ . times ( 1 )
610+ . returning ( |_, _| Ok ( ( ) ) ) ;
611+ let mut kvm = Kvm :: new (
612+ "some_vm" ,
613+ kvmi_mock,
614+ Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
615+ )
616+ . expect ( "Failed to create driver" ) ;
617+ let mut paddr: u64 = 0 ;
618+ let mut buffer: [ u8 ; 4096 ] = [ 0 ; 4096 ] ;
619+ let result_read = Kvm :: read_physical ( & mut kvm, paddr, & mut buffer) ;
620+ paddr = 0 ;
621+ buffer = [ 0 ; 4096 ] ;
622+ let result_write = Kvm :: write_physical ( & mut kvm, paddr, & mut buffer) ;
623+ assert ! ( result_read. is_ok( ) , "Expected ok, got error instead!" ) ;
624+ assert ! ( result_write. is_ok( ) , "Expected ok, got error instead!" ) ;
625+ }
626+
627+ #[ test_case( 1 ; "single vcpu" ) ]
628+ fn test_toggle_intercept ( vcpu_count : u32 ) {
629+ let mut kvmi_mock = MockKVMi :: default ( ) ;
630+ kvmi_mock
631+ . expect_control_cr ( )
632+ . with ( eq ( 0 ) , function ( |x| matches ! ( x, KVMiCr :: Cr3 ) ) , eq ( true ) )
633+ . times ( 1 )
634+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
635+ kvmi_mock
636+ . expect_control_msr ( )
637+ . times ( 0 )
638+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
639+ kvmi_mock
640+ . expect_control_events ( )
641+ . with (
642+ eq ( 1 ) ,
643+ function ( |x| matches ! ( x, KVMiInterceptType :: Breakpoint ) ) ,
644+ eq ( true ) ,
645+ )
646+ . times ( 1 )
647+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
648+ kvmi_mock
649+ . expect_control_events ( )
650+ . with (
651+ eq ( 1 ) ,
652+ function ( |x| matches ! ( x, KVMiInterceptType :: Pagefault ) ) ,
653+ eq ( true ) ,
654+ )
655+ . times ( 1 )
656+ . returning ( |_, _, _| Ok ( ( ) ) ) ;
657+
658+ setup_mock ( & mut kvmi_mock, vcpu_count) ;
659+ let mut kvm = Kvm :: new (
660+ "some_vm" ,
661+ kvmi_mock,
662+ Some ( DriverInitParam :: KVMiSocket ( "/tmp/introspector" . to_string ( ) ) ) ,
663+ )
664+ . expect ( "Failed to create driver" ) ;
665+ let mut vcpu: u16 = 0 ;
666+ let mut intercept_type = InterceptType :: Cr ( CrType :: Cr3 ) ;
667+ let mut enabled: bool = true ;
668+ let result_cr = Kvm :: toggle_intercept ( & mut kvm, vcpu, intercept_type, enabled) ;
669+ vcpu = 1 ;
670+ intercept_type = InterceptType :: Breakpoint ;
671+ enabled = true ;
672+ let result_breakpoint = Kvm :: toggle_intercept ( & mut kvm, vcpu, intercept_type, enabled) ;
673+ vcpu = 1 ;
674+ intercept_type = InterceptType :: Pagefault ;
675+ enabled = true ;
676+ let result_pagefault = Kvm :: toggle_intercept ( & mut kvm, vcpu, intercept_type, enabled) ;
677+ assert ! ( result_cr. is_ok( ) , "Expected ok, got error instead!" ) ;
678+ assert ! ( result_breakpoint. is_ok( ) , "Expected ok, got error instead!" ) ;
679+ assert ! ( result_pagefault. is_ok( ) , "Expected ok, got error instead!" ) ;
680+ }
681+
501682 mock ! {
502683 KVMi { }
503684 trait Debug {
0 commit comments