2
2
// Author(s): Zhao Liu <[email protected] >
3
3
// SPDX-License-Identifier: GPL-2.0-or-later
4
4
5
- use std:: { ffi:: CStr , mem:: size_of, ptr:: NonNull , slice} ;
5
+ use std:: { ffi:: CStr , mem:: size_of, os :: raw :: c_void , ptr:: NonNull , slice} ;
6
6
7
7
use qemu_api:: {
8
8
bindings:: {
@@ -13,7 +13,7 @@ use qemu_api::{
13
13
cell:: { BqlCell , Opaque } ,
14
14
impl_vmstate_forward,
15
15
vmstate:: { VMStateDescription , VMStateField } ,
16
- vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused,
16
+ vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, vmstate_validate ,
17
17
zeroable:: Zeroable ,
18
18
} ;
19
19
@@ -397,3 +397,81 @@ fn test_vmstate_macro_array_of_pointer_wrapped() {
397
397
// The last VMStateField in VMSTATE_FOOC.
398
398
assert_eq ! ( foo_fields[ 4 ] . flags, VMStateFlags :: VMS_END ) ;
399
399
}
400
+
401
+ // =========================== Test VMSTATE_FOOD ===========================
402
+ // Test the use cases of the vmstate macro, corresponding to the following C
403
+ // macro variants:
404
+ // * VMSTATE_FOOD:
405
+ // - VMSTATE_VALIDATE
406
+
407
+ // Add more member fields when vmstate_of/vmstate_struct support "test"
408
+ // parameter.
409
+ struct FooD ;
410
+
411
+ impl FooD {
412
+ fn validate_food_0 ( & self , _version_id : u8 ) -> bool {
413
+ true
414
+ }
415
+
416
+ fn validate_food_1 ( _state : & FooD , _version_id : u8 ) -> bool {
417
+ false
418
+ }
419
+ }
420
+
421
+ fn validate_food_2 ( _state : & FooD , _version_id : u8 ) -> bool {
422
+ true
423
+ }
424
+
425
+ static VMSTATE_FOOD : VMStateDescription = VMStateDescription {
426
+ name : c_str ! ( "foo_d" ) . as_ptr ( ) ,
427
+ version_id : 3 ,
428
+ minimum_version_id : 1 ,
429
+ fields : vmstate_fields ! {
430
+ vmstate_validate!( FooD , c_str!( "foo_d_0" ) , FooD :: validate_food_0) ,
431
+ vmstate_validate!( FooD , c_str!( "foo_d_1" ) , FooD :: validate_food_1) ,
432
+ vmstate_validate!( FooD , c_str!( "foo_d_2" ) , validate_food_2) ,
433
+ } ,
434
+ ..Zeroable :: ZERO
435
+ } ;
436
+
437
+ #[ test]
438
+ fn test_vmstate_validate ( ) {
439
+ let foo_fields: & [ VMStateField ] = unsafe { slice:: from_raw_parts ( VMSTATE_FOOD . fields , 4 ) } ;
440
+ let mut foo_d = FooD ;
441
+ let foo_d_p = std:: ptr:: addr_of_mut!( foo_d) . cast :: < c_void > ( ) ;
442
+
443
+ // 1st VMStateField in VMSTATE_FOOD
444
+ assert_eq ! (
445
+ unsafe { CStr :: from_ptr( foo_fields[ 0 ] . name) } . to_bytes_with_nul( ) ,
446
+ b"foo_d_0\0 "
447
+ ) ;
448
+ assert_eq ! ( foo_fields[ 0 ] . offset, 0 ) ;
449
+ assert_eq ! ( foo_fields[ 0 ] . num_offset, 0 ) ;
450
+ assert ! ( foo_fields[ 0 ] . info. is_null( ) ) ;
451
+ assert_eq ! ( foo_fields[ 0 ] . version_id, 0 ) ;
452
+ assert_eq ! ( foo_fields[ 0 ] . size, 0 ) ;
453
+ assert_eq ! ( foo_fields[ 0 ] . num, 0 ) ;
454
+ assert_eq ! (
455
+ foo_fields[ 0 ] . flags. 0 ,
456
+ VMStateFlags :: VMS_ARRAY . 0 | VMStateFlags :: VMS_MUST_EXIST . 0
457
+ ) ;
458
+ assert ! ( foo_fields[ 0 ] . vmsd. is_null( ) ) ;
459
+ assert ! ( unsafe { foo_fields[ 0 ] . field_exists. unwrap( ) ( foo_d_p, 0 ) } ) ;
460
+
461
+ // 2nd VMStateField in VMSTATE_FOOD
462
+ assert_eq ! (
463
+ unsafe { CStr :: from_ptr( foo_fields[ 1 ] . name) } . to_bytes_with_nul( ) ,
464
+ b"foo_d_1\0 "
465
+ ) ;
466
+ assert ! ( !unsafe { foo_fields[ 1 ] . field_exists. unwrap( ) ( foo_d_p, 1 ) } ) ;
467
+
468
+ // 3rd VMStateField in VMSTATE_FOOD
469
+ assert_eq ! (
470
+ unsafe { CStr :: from_ptr( foo_fields[ 2 ] . name) } . to_bytes_with_nul( ) ,
471
+ b"foo_d_2\0 "
472
+ ) ;
473
+ assert ! ( unsafe { foo_fields[ 2 ] . field_exists. unwrap( ) ( foo_d_p, 2 ) } ) ;
474
+
475
+ // The last VMStateField in VMSTATE_FOOD.
476
+ assert_eq ! ( foo_fields[ 3 ] . flags, VMStateFlags :: VMS_END ) ;
477
+ }
0 commit comments