119985021SZhao Liu // Copyright (C) 2025 Intel Corporation. 219985021SZhao Liu // Author(s): Zhao Liu <zhai1.liu@intel.com> 319985021SZhao Liu // SPDX-License-Identifier: GPL-2.0-or-later 419985021SZhao Liu 5*8df1b001SZhao Liu use std::{ffi::CStr, mem::size_of, ptr::NonNull, slice}; 619985021SZhao Liu 719985021SZhao Liu use qemu_api::{ 857c327f3SZhao Liu bindings::{ 9*8df1b001SZhao Liu vmstate_info_bool, vmstate_info_int32, vmstate_info_int64, vmstate_info_int8, 10*8df1b001SZhao Liu vmstate_info_uint64, vmstate_info_uint8, vmstate_info_unused_buffer, VMStateFlags, 1157c327f3SZhao Liu }, 1219985021SZhao Liu c_str, 13*8df1b001SZhao Liu cell::{BqlCell, Opaque}, 14*8df1b001SZhao Liu impl_vmstate_forward, 1519985021SZhao Liu vmstate::{VMStateDescription, VMStateField}, 1657c327f3SZhao Liu vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, 1719985021SZhao Liu zeroable::Zeroable, 1819985021SZhao Liu }; 1919985021SZhao Liu 2019985021SZhao Liu const FOO_ARRAY_MAX: usize = 3; 2119985021SZhao Liu 2219985021SZhao Liu // =========================== Test VMSTATE_FOOA =========================== 2319985021SZhao Liu // Test the use cases of the vmstate macro, corresponding to the following C 2419985021SZhao Liu // macro variants: 2519985021SZhao Liu // * VMSTATE_FOOA: 2619985021SZhao Liu // - VMSTATE_U16 2719985021SZhao Liu // - VMSTATE_UNUSED 2819985021SZhao Liu // - VMSTATE_VARRAY_UINT16_UNSAFE 2919985021SZhao Liu // - VMSTATE_VARRAY_MULTIPLY 3019985021SZhao Liu #[repr(C)] 3119985021SZhao Liu #[derive(qemu_api_macros::offsets)] 3219985021SZhao Liu struct FooA { 3319985021SZhao Liu arr: [u8; FOO_ARRAY_MAX], 3419985021SZhao Liu num: u16, 3519985021SZhao Liu arr_mul: [i8; FOO_ARRAY_MAX], 3619985021SZhao Liu num_mul: u32, 3719985021SZhao Liu elem: i8, 3819985021SZhao Liu } 3919985021SZhao Liu 4019985021SZhao Liu static VMSTATE_FOOA: VMStateDescription = VMStateDescription { 4119985021SZhao Liu name: c_str!("foo_a").as_ptr(), 4219985021SZhao Liu version_id: 1, 4319985021SZhao Liu minimum_version_id: 1, 4419985021SZhao Liu fields: vmstate_fields! { 4519985021SZhao Liu vmstate_of!(FooA, elem), 4619985021SZhao Liu vmstate_unused!(size_of::<i64>()), 4719985021SZhao Liu vmstate_of!(FooA, arr[0 .. num]).with_version_id(0), 4819985021SZhao Liu vmstate_of!(FooA, arr_mul[0 .. num_mul * 16]), 4919985021SZhao Liu }, 5019985021SZhao Liu ..Zeroable::ZERO 5119985021SZhao Liu }; 5219985021SZhao Liu 5319985021SZhao Liu #[test] 5419985021SZhao Liu fn test_vmstate_uint16() { 5519985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 5619985021SZhao Liu 5719985021SZhao Liu // 1st VMStateField ("elem") in VMSTATE_FOOA (corresponding to VMSTATE_UINT16) 5819985021SZhao Liu assert_eq!( 5919985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), 6019985021SZhao Liu b"elem\0" 6119985021SZhao Liu ); 6219985021SZhao Liu assert_eq!(foo_fields[0].offset, 16); 6319985021SZhao Liu assert_eq!(foo_fields[0].num_offset, 0); 6419985021SZhao Liu assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int8 }); 6519985021SZhao Liu assert_eq!(foo_fields[0].version_id, 0); 6619985021SZhao Liu assert_eq!(foo_fields[0].size, 1); 6719985021SZhao Liu assert_eq!(foo_fields[0].num, 0); 6819985021SZhao Liu assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE); 6919985021SZhao Liu assert!(foo_fields[0].vmsd.is_null()); 7019985021SZhao Liu assert!(foo_fields[0].field_exists.is_none()); 7119985021SZhao Liu } 7219985021SZhao Liu 7319985021SZhao Liu #[test] 7419985021SZhao Liu fn test_vmstate_unused() { 7519985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 7619985021SZhao Liu 7719985021SZhao Liu // 2nd VMStateField ("unused") in VMSTATE_FOOA (corresponding to VMSTATE_UNUSED) 7819985021SZhao Liu assert_eq!( 7919985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), 8019985021SZhao Liu b"unused\0" 8119985021SZhao Liu ); 8219985021SZhao Liu assert_eq!(foo_fields[1].offset, 0); 8319985021SZhao Liu assert_eq!(foo_fields[1].num_offset, 0); 8419985021SZhao Liu assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_unused_buffer }); 8519985021SZhao Liu assert_eq!(foo_fields[1].version_id, 0); 8619985021SZhao Liu assert_eq!(foo_fields[1].size, 8); 8719985021SZhao Liu assert_eq!(foo_fields[1].num, 0); 8819985021SZhao Liu assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_BUFFER); 8919985021SZhao Liu assert!(foo_fields[1].vmsd.is_null()); 9019985021SZhao Liu assert!(foo_fields[1].field_exists.is_none()); 9119985021SZhao Liu } 9219985021SZhao Liu 9319985021SZhao Liu #[test] 9419985021SZhao Liu fn test_vmstate_varray_uint16_unsafe() { 9519985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 9619985021SZhao Liu 9719985021SZhao Liu // 3rd VMStateField ("arr") in VMSTATE_FOOA (corresponding to 9819985021SZhao Liu // VMSTATE_VARRAY_UINT16_UNSAFE) 9919985021SZhao Liu assert_eq!( 10019985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), 10119985021SZhao Liu b"arr\0" 10219985021SZhao Liu ); 10319985021SZhao Liu assert_eq!(foo_fields[2].offset, 0); 10419985021SZhao Liu assert_eq!(foo_fields[2].num_offset, 4); 10519985021SZhao Liu assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); 10619985021SZhao Liu assert_eq!(foo_fields[2].version_id, 0); 10719985021SZhao Liu assert_eq!(foo_fields[2].size, 1); 10819985021SZhao Liu assert_eq!(foo_fields[2].num, 0); 10919985021SZhao Liu assert_eq!(foo_fields[2].flags, VMStateFlags::VMS_VARRAY_UINT16); 11019985021SZhao Liu assert!(foo_fields[2].vmsd.is_null()); 11119985021SZhao Liu assert!(foo_fields[2].field_exists.is_none()); 11219985021SZhao Liu } 11319985021SZhao Liu 11419985021SZhao Liu #[test] 11519985021SZhao Liu fn test_vmstate_varray_multiply() { 11619985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 11719985021SZhao Liu 11819985021SZhao Liu // 4th VMStateField ("arr_mul") in VMSTATE_FOOA (corresponding to 11919985021SZhao Liu // VMSTATE_VARRAY_MULTIPLY) 12019985021SZhao Liu assert_eq!( 12119985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), 12219985021SZhao Liu b"arr_mul\0" 12319985021SZhao Liu ); 12419985021SZhao Liu assert_eq!(foo_fields[3].offset, 6); 12519985021SZhao Liu assert_eq!(foo_fields[3].num_offset, 12); 12619985021SZhao Liu assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_int8 }); 12719985021SZhao Liu assert_eq!(foo_fields[3].version_id, 0); 12819985021SZhao Liu assert_eq!(foo_fields[3].size, 1); 12919985021SZhao Liu assert_eq!(foo_fields[3].num, 16); 13019985021SZhao Liu assert_eq!( 13119985021SZhao Liu foo_fields[3].flags.0, 13219985021SZhao Liu VMStateFlags::VMS_VARRAY_UINT32.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0 13319985021SZhao Liu ); 13419985021SZhao Liu assert!(foo_fields[3].vmsd.is_null()); 13519985021SZhao Liu assert!(foo_fields[3].field_exists.is_none()); 13619985021SZhao Liu 13719985021SZhao Liu // The last VMStateField in VMSTATE_FOOA. 13819985021SZhao Liu assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END); 13919985021SZhao Liu } 14057c327f3SZhao Liu 14157c327f3SZhao Liu // =========================== Test VMSTATE_FOOB =========================== 14257c327f3SZhao Liu // Test the use cases of the vmstate macro, corresponding to the following C 14357c327f3SZhao Liu // macro variants: 14457c327f3SZhao Liu // * VMSTATE_FOOB: 14557c327f3SZhao Liu // - VMSTATE_BOOL_V 14657c327f3SZhao Liu // - VMSTATE_U64 14757c327f3SZhao Liu // - VMSTATE_STRUCT_VARRAY_UINT8 14857c327f3SZhao Liu // - (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32 14957c327f3SZhao Liu // - VMSTATE_ARRAY 15057c327f3SZhao Liu #[repr(C)] 15157c327f3SZhao Liu #[derive(qemu_api_macros::offsets)] 15257c327f3SZhao Liu struct FooB { 15357c327f3SZhao Liu arr_a: [FooA; FOO_ARRAY_MAX], 15457c327f3SZhao Liu num_a: u8, 15557c327f3SZhao Liu arr_a_mul: [FooA; FOO_ARRAY_MAX], 15657c327f3SZhao Liu num_a_mul: u32, 15757c327f3SZhao Liu wrap: BqlCell<u64>, 15857c327f3SZhao Liu val: bool, 15957c327f3SZhao Liu // FIXME: Use Timer array. Now we can't since it's hard to link savevm.c to test. 16057c327f3SZhao Liu arr_i64: [i64; FOO_ARRAY_MAX], 16157c327f3SZhao Liu } 16257c327f3SZhao Liu 16357c327f3SZhao Liu static VMSTATE_FOOB: VMStateDescription = VMStateDescription { 16457c327f3SZhao Liu name: c_str!("foo_b").as_ptr(), 16557c327f3SZhao Liu version_id: 2, 16657c327f3SZhao Liu minimum_version_id: 1, 16757c327f3SZhao Liu fields: vmstate_fields! { 16857c327f3SZhao Liu vmstate_of!(FooB, val).with_version_id(2), 16957c327f3SZhao Liu vmstate_of!(FooB, wrap), 17057c327f3SZhao Liu vmstate_struct!(FooB, arr_a[0 .. num_a], &VMSTATE_FOOA, FooA).with_version_id(1), 17157c327f3SZhao Liu vmstate_struct!(FooB, arr_a_mul[0 .. num_a_mul * 32], &VMSTATE_FOOA, FooA).with_version_id(2), 17257c327f3SZhao Liu vmstate_of!(FooB, arr_i64), 17357c327f3SZhao Liu }, 17457c327f3SZhao Liu ..Zeroable::ZERO 17557c327f3SZhao Liu }; 17657c327f3SZhao Liu 17757c327f3SZhao Liu #[test] 17857c327f3SZhao Liu fn test_vmstate_bool_v() { 17957c327f3SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) }; 18057c327f3SZhao Liu 18157c327f3SZhao Liu // 1st VMStateField ("val") in VMSTATE_FOOB (corresponding to VMSTATE_BOOL_V) 18257c327f3SZhao Liu assert_eq!( 18357c327f3SZhao Liu unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), 18457c327f3SZhao Liu b"val\0" 18557c327f3SZhao Liu ); 18657c327f3SZhao Liu assert_eq!(foo_fields[0].offset, 136); 18757c327f3SZhao Liu assert_eq!(foo_fields[0].num_offset, 0); 18857c327f3SZhao Liu assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_bool }); 18957c327f3SZhao Liu assert_eq!(foo_fields[0].version_id, 2); 19057c327f3SZhao Liu assert_eq!(foo_fields[0].size, 1); 19157c327f3SZhao Liu assert_eq!(foo_fields[0].num, 0); 19257c327f3SZhao Liu assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE); 19357c327f3SZhao Liu assert!(foo_fields[0].vmsd.is_null()); 19457c327f3SZhao Liu assert!(foo_fields[0].field_exists.is_none()); 19557c327f3SZhao Liu } 19657c327f3SZhao Liu 19757c327f3SZhao Liu #[test] 19857c327f3SZhao Liu fn test_vmstate_uint64() { 19957c327f3SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) }; 20057c327f3SZhao Liu 20157c327f3SZhao Liu // 2nd VMStateField ("wrap") in VMSTATE_FOOB (corresponding to VMSTATE_U64) 20257c327f3SZhao Liu assert_eq!( 20357c327f3SZhao Liu unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), 20457c327f3SZhao Liu b"wrap\0" 20557c327f3SZhao Liu ); 20657c327f3SZhao Liu assert_eq!(foo_fields[1].offset, 128); 20757c327f3SZhao Liu assert_eq!(foo_fields[1].num_offset, 0); 20857c327f3SZhao Liu assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_uint64 }); 20957c327f3SZhao Liu assert_eq!(foo_fields[1].version_id, 0); 21057c327f3SZhao Liu assert_eq!(foo_fields[1].size, 8); 21157c327f3SZhao Liu assert_eq!(foo_fields[1].num, 0); 21257c327f3SZhao Liu assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_SINGLE); 21357c327f3SZhao Liu assert!(foo_fields[1].vmsd.is_null()); 21457c327f3SZhao Liu assert!(foo_fields[1].field_exists.is_none()); 21557c327f3SZhao Liu } 21657c327f3SZhao Liu 21757c327f3SZhao Liu #[test] 21857c327f3SZhao Liu fn test_vmstate_struct_varray_uint8() { 21957c327f3SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) }; 22057c327f3SZhao Liu 22157c327f3SZhao Liu // 3rd VMStateField ("arr_a") in VMSTATE_FOOB (corresponding to 22257c327f3SZhao Liu // VMSTATE_STRUCT_VARRAY_UINT8) 22357c327f3SZhao Liu assert_eq!( 22457c327f3SZhao Liu unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), 22557c327f3SZhao Liu b"arr_a\0" 22657c327f3SZhao Liu ); 22757c327f3SZhao Liu assert_eq!(foo_fields[2].offset, 0); 22857c327f3SZhao Liu assert_eq!(foo_fields[2].num_offset, 60); 22957c327f3SZhao Liu assert!(foo_fields[2].info.is_null()); // VMSTATE_STRUCT_VARRAY_UINT8 doesn't set info field. 23057c327f3SZhao Liu assert_eq!(foo_fields[2].version_id, 1); 23157c327f3SZhao Liu assert_eq!(foo_fields[2].size, 20); 23257c327f3SZhao Liu assert_eq!(foo_fields[2].num, 0); 23357c327f3SZhao Liu assert_eq!( 23457c327f3SZhao Liu foo_fields[2].flags.0, 23557c327f3SZhao Liu VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_VARRAY_UINT8.0 23657c327f3SZhao Liu ); 23757c327f3SZhao Liu assert_eq!(foo_fields[2].vmsd, &VMSTATE_FOOA); 23857c327f3SZhao Liu assert!(foo_fields[2].field_exists.is_none()); 23957c327f3SZhao Liu } 24057c327f3SZhao Liu 24157c327f3SZhao Liu #[test] 24257c327f3SZhao Liu fn test_vmstate_struct_varray_uint32_multiply() { 24357c327f3SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) }; 24457c327f3SZhao Liu 24557c327f3SZhao Liu // 4th VMStateField ("arr_a_mul") in VMSTATE_FOOB (corresponding to 24657c327f3SZhao Liu // (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32) 24757c327f3SZhao Liu assert_eq!( 24857c327f3SZhao Liu unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), 24957c327f3SZhao Liu b"arr_a_mul\0" 25057c327f3SZhao Liu ); 25157c327f3SZhao Liu assert_eq!(foo_fields[3].offset, 64); 25257c327f3SZhao Liu assert_eq!(foo_fields[3].num_offset, 124); 25357c327f3SZhao Liu assert!(foo_fields[3].info.is_null()); // VMSTATE_STRUCT_VARRAY_UINT8 doesn't set info field. 25457c327f3SZhao Liu assert_eq!(foo_fields[3].version_id, 2); 25557c327f3SZhao Liu assert_eq!(foo_fields[3].size, 20); 25657c327f3SZhao Liu assert_eq!(foo_fields[3].num, 32); 25757c327f3SZhao Liu assert_eq!( 25857c327f3SZhao Liu foo_fields[3].flags.0, 25957c327f3SZhao Liu VMStateFlags::VMS_STRUCT.0 26057c327f3SZhao Liu | VMStateFlags::VMS_VARRAY_UINT32.0 26157c327f3SZhao Liu | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0 26257c327f3SZhao Liu ); 26357c327f3SZhao Liu assert_eq!(foo_fields[3].vmsd, &VMSTATE_FOOA); 26457c327f3SZhao Liu assert!(foo_fields[3].field_exists.is_none()); 26557c327f3SZhao Liu } 26657c327f3SZhao Liu 26757c327f3SZhao Liu #[test] 26857c327f3SZhao Liu fn test_vmstate_macro_array() { 26957c327f3SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) }; 27057c327f3SZhao Liu 27157c327f3SZhao Liu // 5th VMStateField ("arr_i64") in VMSTATE_FOOB (corresponding to 27257c327f3SZhao Liu // VMSTATE_ARRAY) 27357c327f3SZhao Liu assert_eq!( 27457c327f3SZhao Liu unsafe { CStr::from_ptr(foo_fields[4].name) }.to_bytes_with_nul(), 27557c327f3SZhao Liu b"arr_i64\0" 27657c327f3SZhao Liu ); 27757c327f3SZhao Liu assert_eq!(foo_fields[4].offset, 144); 27857c327f3SZhao Liu assert_eq!(foo_fields[4].num_offset, 0); 27957c327f3SZhao Liu assert_eq!(foo_fields[4].info, unsafe { &vmstate_info_int64 }); 28057c327f3SZhao Liu assert_eq!(foo_fields[4].version_id, 0); 28157c327f3SZhao Liu assert_eq!(foo_fields[4].size, 8); 28257c327f3SZhao Liu assert_eq!(foo_fields[4].num, FOO_ARRAY_MAX as i32); 28357c327f3SZhao Liu assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_ARRAY); 28457c327f3SZhao Liu assert!(foo_fields[4].vmsd.is_null()); 28557c327f3SZhao Liu assert!(foo_fields[4].field_exists.is_none()); 28657c327f3SZhao Liu 28757c327f3SZhao Liu // The last VMStateField in VMSTATE_FOOB. 28857c327f3SZhao Liu assert_eq!(foo_fields[5].flags, VMStateFlags::VMS_END); 28957c327f3SZhao Liu } 290*8df1b001SZhao Liu 291*8df1b001SZhao Liu // =========================== Test VMSTATE_FOOC =========================== 292*8df1b001SZhao Liu // Test the use cases of the vmstate macro, corresponding to the following C 293*8df1b001SZhao Liu // macro variants: 294*8df1b001SZhao Liu // * VMSTATE_FOOC: 295*8df1b001SZhao Liu // - VMSTATE_POINTER 296*8df1b001SZhao Liu // - VMSTATE_ARRAY_OF_POINTER 297*8df1b001SZhao Liu struct FooCWrapper([Opaque<*mut u8>; FOO_ARRAY_MAX]); // Though Opaque<> array is almost impossible. 298*8df1b001SZhao Liu 299*8df1b001SZhao Liu impl_vmstate_forward!(FooCWrapper); 300*8df1b001SZhao Liu 301*8df1b001SZhao Liu #[repr(C)] 302*8df1b001SZhao Liu #[derive(qemu_api_macros::offsets)] 303*8df1b001SZhao Liu struct FooC { 304*8df1b001SZhao Liu ptr: *const i32, 305*8df1b001SZhao Liu ptr_a: NonNull<FooA>, 306*8df1b001SZhao Liu arr_ptr: [Box<u8>; FOO_ARRAY_MAX], 307*8df1b001SZhao Liu arr_ptr_wrap: FooCWrapper, 308*8df1b001SZhao Liu } 309*8df1b001SZhao Liu 310*8df1b001SZhao Liu static VMSTATE_FOOC: VMStateDescription = VMStateDescription { 311*8df1b001SZhao Liu name: c_str!("foo_c").as_ptr(), 312*8df1b001SZhao Liu version_id: 3, 313*8df1b001SZhao Liu minimum_version_id: 1, 314*8df1b001SZhao Liu fields: vmstate_fields! { 315*8df1b001SZhao Liu vmstate_of!(FooC, ptr).with_version_id(2), 316*8df1b001SZhao Liu // FIXME: Currently vmstate_struct doesn't support the pointer to structure. 317*8df1b001SZhao Liu // VMSTATE_STRUCT_POINTER: vmstate_struct!(FooC, ptr_a, VMSTATE_FOOA, NonNull<FooA>) 318*8df1b001SZhao Liu vmstate_unused!(size_of::<NonNull<FooA>>()), 319*8df1b001SZhao Liu vmstate_of!(FooC, arr_ptr), 320*8df1b001SZhao Liu vmstate_of!(FooC, arr_ptr_wrap), 321*8df1b001SZhao Liu }, 322*8df1b001SZhao Liu ..Zeroable::ZERO 323*8df1b001SZhao Liu }; 324*8df1b001SZhao Liu 325*8df1b001SZhao Liu const PTR_SIZE: usize = size_of::<*mut ()>(); 326*8df1b001SZhao Liu 327*8df1b001SZhao Liu #[test] 328*8df1b001SZhao Liu fn test_vmstate_pointer() { 329*8df1b001SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOC.fields, 6) }; 330*8df1b001SZhao Liu 331*8df1b001SZhao Liu // 1st VMStateField ("ptr") in VMSTATE_FOOC (corresponding to VMSTATE_POINTER) 332*8df1b001SZhao Liu assert_eq!( 333*8df1b001SZhao Liu unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), 334*8df1b001SZhao Liu b"ptr\0" 335*8df1b001SZhao Liu ); 336*8df1b001SZhao Liu assert_eq!(foo_fields[0].offset, 0); 337*8df1b001SZhao Liu assert_eq!(foo_fields[0].num_offset, 0); 338*8df1b001SZhao Liu assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int32 }); 339*8df1b001SZhao Liu assert_eq!(foo_fields[0].version_id, 2); 340*8df1b001SZhao Liu assert_eq!(foo_fields[0].size, 4); 341*8df1b001SZhao Liu assert_eq!(foo_fields[0].num, 0); 342*8df1b001SZhao Liu assert_eq!( 343*8df1b001SZhao Liu foo_fields[0].flags.0, 344*8df1b001SZhao Liu VMStateFlags::VMS_SINGLE.0 | VMStateFlags::VMS_POINTER.0 345*8df1b001SZhao Liu ); 346*8df1b001SZhao Liu assert!(foo_fields[0].vmsd.is_null()); 347*8df1b001SZhao Liu assert!(foo_fields[0].field_exists.is_none()); 348*8df1b001SZhao Liu } 349*8df1b001SZhao Liu 350*8df1b001SZhao Liu #[test] 351*8df1b001SZhao Liu fn test_vmstate_macro_array_of_pointer() { 352*8df1b001SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOC.fields, 6) }; 353*8df1b001SZhao Liu 354*8df1b001SZhao Liu // 3rd VMStateField ("arr_ptr") in VMSTATE_FOOC (corresponding to 355*8df1b001SZhao Liu // VMSTATE_ARRAY_OF_POINTER) 356*8df1b001SZhao Liu assert_eq!( 357*8df1b001SZhao Liu unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), 358*8df1b001SZhao Liu b"arr_ptr\0" 359*8df1b001SZhao Liu ); 360*8df1b001SZhao Liu assert_eq!(foo_fields[2].offset, 2 * PTR_SIZE); 361*8df1b001SZhao Liu assert_eq!(foo_fields[2].num_offset, 0); 362*8df1b001SZhao Liu assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); 363*8df1b001SZhao Liu assert_eq!(foo_fields[2].version_id, 0); 364*8df1b001SZhao Liu assert_eq!(foo_fields[2].size, PTR_SIZE); 365*8df1b001SZhao Liu assert_eq!(foo_fields[2].num, FOO_ARRAY_MAX as i32); 366*8df1b001SZhao Liu assert_eq!( 367*8df1b001SZhao Liu foo_fields[2].flags.0, 368*8df1b001SZhao Liu VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0 369*8df1b001SZhao Liu ); 370*8df1b001SZhao Liu assert!(foo_fields[2].vmsd.is_null()); 371*8df1b001SZhao Liu assert!(foo_fields[2].field_exists.is_none()); 372*8df1b001SZhao Liu } 373*8df1b001SZhao Liu 374*8df1b001SZhao Liu #[test] 375*8df1b001SZhao Liu fn test_vmstate_macro_array_of_pointer_wrapped() { 376*8df1b001SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOC.fields, 6) }; 377*8df1b001SZhao Liu 378*8df1b001SZhao Liu // 4th VMStateField ("arr_ptr_wrap") in VMSTATE_FOOC (corresponding to 379*8df1b001SZhao Liu // VMSTATE_ARRAY_OF_POINTER) 380*8df1b001SZhao Liu assert_eq!( 381*8df1b001SZhao Liu unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), 382*8df1b001SZhao Liu b"arr_ptr_wrap\0" 383*8df1b001SZhao Liu ); 384*8df1b001SZhao Liu assert_eq!(foo_fields[3].offset, (FOO_ARRAY_MAX + 2) * PTR_SIZE); 385*8df1b001SZhao Liu assert_eq!(foo_fields[3].num_offset, 0); 386*8df1b001SZhao Liu assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); 387*8df1b001SZhao Liu assert_eq!(foo_fields[3].version_id, 0); 388*8df1b001SZhao Liu assert_eq!(foo_fields[3].size, PTR_SIZE); 389*8df1b001SZhao Liu assert_eq!(foo_fields[3].num, FOO_ARRAY_MAX as i32); 390*8df1b001SZhao Liu assert_eq!( 391*8df1b001SZhao Liu foo_fields[2].flags.0, 392*8df1b001SZhao Liu VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0 393*8df1b001SZhao Liu ); 394*8df1b001SZhao Liu assert!(foo_fields[3].vmsd.is_null()); 395*8df1b001SZhao Liu assert!(foo_fields[3].field_exists.is_none()); 396*8df1b001SZhao Liu 397*8df1b001SZhao Liu // The last VMStateField in VMSTATE_FOOC. 398*8df1b001SZhao Liu assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END); 399*8df1b001SZhao Liu } 400