From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org,
Zhao Liu <zhao1.liu@intel.com>
Subject: [PATCH v3 11/15] rust/vmstate: Add unit test for vmstate_of macro
Date: Tue, 18 Mar 2025 21:02:15 +0800 [thread overview]
Message-ID: <20250318130219.1799170-12-zhao1.liu@intel.com> (raw)
In-Reply-To: <20250318130219.1799170-1-zhao1.liu@intel.com>
The vmstate has too many combinations of VMStateFlags and VMStateField.
Currently, the best way to test is to ensure that the Rust vmstate
definition is consistent with the (possibly corresponding) C version.
Add a unit test to cover some patterns accepted by vmstate_of macro,
which correspond to the following C version macros:
* VMSTATE_U16
* VMSTATE_UNUSED
* VMSTATE_VARRAY_UINT16_UNSAFE
* VMSTATE_VARRAY_MULTIPLY
Note: Because vmstate_info_* are defined in vmstate-types.c, it's
necessary to link libmigration to rust unit tests. In the future,
maybe it's possible to spilt libmigration from rust_qemu_api_objs.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
rust/qemu-api/meson.build | 5 +-
rust/qemu-api/tests/tests.rs | 2 +
rust/qemu-api/tests/vmstate_tests.rs | 119 +++++++++++++++++++++++++++
3 files changed, 124 insertions(+), 2 deletions(-)
create mode 100644 rust/qemu-api/tests/vmstate_tests.rs
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index a3f226ccc2a5..858685ddd4a4 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -58,7 +58,8 @@ rust_qemu_api_objs = static_library(
libchardev.extract_all_objects(recursive: false),
libcrypto.extract_all_objects(recursive: false),
libauthz.extract_all_objects(recursive: false),
- libio.extract_all_objects(recursive: false)])
+ libio.extract_all_objects(recursive: false),
+ libmigration.extract_all_objects(recursive: false)])
rust_qemu_api_deps = declare_dependency(
dependencies: [
qom_ss.dependencies(),
@@ -71,7 +72,7 @@ rust_qemu_api_deps = declare_dependency(
test('rust-qemu-api-integration',
executable(
'rust-qemu-api-integration',
- 'tests/tests.rs',
+ files('tests/tests.rs', 'tests/vmstate_tests.rs'),
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_args: ['--test'],
install: false,
diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs
index 269122e7ec19..99a7aab6fed9 100644
--- a/rust/qemu-api/tests/tests.rs
+++ b/rust/qemu-api/tests/tests.rs
@@ -17,6 +17,8 @@
zeroable::Zeroable,
};
+mod vmstate_tests;
+
// Test that macros can compile.
pub static VMSTATE: VMStateDescription = VMStateDescription {
name: c_str!("name").as_ptr(),
diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vmstate_tests.rs
new file mode 100644
index 000000000000..29d4ea774850
--- /dev/null
+++ b/rust/qemu-api/tests/vmstate_tests.rs
@@ -0,0 +1,119 @@
+// Copyright (C) 2025 Intel Corporation.
+// Author(s): Zhao Liu <zhai1.liu@intel.com>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+use std::{ffi::CStr, mem::size_of, slice};
+
+use qemu_api::{
+ bindings::{vmstate_info_int8, vmstate_info_uint8, vmstate_info_unused_buffer, VMStateFlags},
+ c_str,
+ vmstate::{VMStateDescription, VMStateField},
+ vmstate_fields, vmstate_of, vmstate_unused,
+ zeroable::Zeroable,
+};
+
+const FOO_ARRAY_MAX: usize = 3;
+
+// =========================== Test VMSTATE_FOOA ===========================
+// Test the use cases of the vmstate macro, corresponding to the following C
+// macro variants:
+// * VMSTATE_FOOA:
+// - VMSTATE_U16
+// - VMSTATE_UNUSED
+// - VMSTATE_VARRAY_UINT16_UNSAFE
+// - VMSTATE_VARRAY_MULTIPLY
+#[repr(C)]
+#[derive(qemu_api_macros::offsets)]
+struct FooA {
+ arr: [u8; FOO_ARRAY_MAX],
+ num: u16,
+ arr_mul: [i8; FOO_ARRAY_MAX],
+ num_mul: u32,
+ elem: i8,
+}
+
+static VMSTATE_FOOA: VMStateDescription = VMStateDescription {
+ name: c_str!("foo_a").as_ptr(),
+ version_id: 1,
+ minimum_version_id: 1,
+ fields: vmstate_fields! {
+ vmstate_of!(FooA, elem),
+ vmstate_unused!(size_of::<i64>()),
+ vmstate_of!(FooA, arr[0 .. num]).with_version_id(0),
+ vmstate_of!(FooA, arr_mul[0 .. num_mul * 16]),
+ },
+ ..Zeroable::ZERO
+};
+
+#[test]
+fn test_vmstate_macro_fooa() {
+ let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) };
+
+ // 1st VMStateField ("elem") in VMSTATE_FOOA (corresponding to VMSTATE_U16)
+ assert_eq!(
+ unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(),
+ b"elem\0"
+ );
+ assert_eq!(foo_fields[0].offset, 16);
+ assert_eq!(foo_fields[0].num_offset, 0);
+ assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int8 });
+ assert_eq!(foo_fields[0].version_id, 0);
+ assert_eq!(foo_fields[0].size, 1);
+ assert_eq!(foo_fields[0].num, 0);
+ assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE);
+ assert_eq!(foo_fields[0].vmsd.is_null(), true);
+ assert_eq!(foo_fields[0].field_exists.is_none(), true);
+
+ // 2nd VMStateField ("unused") in VMSTATE_FOOA (corresponding to VMSTATE_UNUSED)
+ assert_eq!(
+ unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(),
+ b"unused\0"
+ );
+ assert_eq!(foo_fields[1].offset, 0);
+ assert_eq!(foo_fields[1].num_offset, 0);
+ assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_unused_buffer });
+ assert_eq!(foo_fields[1].version_id, 0);
+ assert_eq!(foo_fields[1].size, 8);
+ assert_eq!(foo_fields[1].num, 0);
+ assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_BUFFER);
+ assert_eq!(foo_fields[1].vmsd.is_null(), true);
+ assert_eq!(foo_fields[1].field_exists.is_none(), true);
+
+ // 3rd VMStateField ("arr") in VMSTATE_FOOA (corresponding to
+ // VMSTATE_VARRAY_UINT16_UNSAFE)
+ assert_eq!(
+ unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(),
+ b"arr\0"
+ );
+ assert_eq!(foo_fields[2].offset, 0);
+ assert_eq!(foo_fields[2].num_offset, 4);
+ assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 });
+ assert_eq!(foo_fields[2].version_id, 0);
+ assert_eq!(foo_fields[2].size, 1);
+ assert_eq!(foo_fields[2].num, 0);
+ assert_eq!(foo_fields[2].flags, VMStateFlags::VMS_VARRAY_UINT16);
+ assert_eq!(foo_fields[2].vmsd.is_null(), true);
+ assert_eq!(foo_fields[2].field_exists.is_none(), true);
+
+ // 4th VMStateField ("arr_mul") in VMSTATE_FOOA (corresponding to
+ // VMSTATE_VARRAY_MULTIPLY)
+ assert_eq!(
+ unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(),
+ b"arr_mul\0"
+ );
+ assert_eq!(foo_fields[3].offset, 6);
+ assert_eq!(foo_fields[3].num_offset, 12);
+ assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_int8 });
+ assert_eq!(foo_fields[3].version_id, 0);
+ assert_eq!(foo_fields[3].size, 1);
+ assert_eq!(foo_fields[3].num, 16);
+ assert_eq!(
+ foo_fields[3].flags.0,
+ VMStateFlags::VMS_VARRAY_UINT32.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0
+ );
+ assert_eq!(foo_fields[3].vmsd.is_null(), true);
+ assert_eq!(foo_fields[3].field_exists.is_none(), true);
+
+ // The last VMStateField in VMSTATE_FOOA.
+ assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END);
+}
--
2.34.1
next prev parent reply other threads:[~2025-03-18 12:44 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-18 13:02 [PATCH v3 00/15] rust/vmstate: Clean up, fix, enhance & test Zhao Liu
2025-03-18 13:02 ` [PATCH v3 01/15] rust/vmstate: Remove unnecessary unsafe Zhao Liu
2025-03-18 13:02 ` [PATCH v3 02/15] rust/vmstate: Fix num_offset in vmstate macros Zhao Liu
2025-03-18 13:02 ` [PATCH v3 03/15] rust/vmstate: Fix num field when varray flags are set Zhao Liu
2025-03-18 13:02 ` [PATCH v3 04/15] rust/vmstate: Fix size field of VMStateField with VMS_ARRAY_OF_POINTER flag Zhao Liu
2025-03-18 13:02 ` [PATCH v3 05/15] rust/vmstate: Fix type check for varray in vmstate_struct Zhao Liu
2025-03-18 13:02 ` [PATCH v3 06/15] rust/vmstate: Fix "cannot infer type" error " Zhao Liu
2025-03-18 13:02 ` [PATCH v3 07/15] rust/vmstate: Fix unnecessary VMState bound of with_varray_flag() Zhao Liu
2025-03-18 13:02 ` [PATCH v3 08/15] rust/vmstate: Relax array check when build varray in vmstate_struct Zhao Liu
2025-03-18 13:02 ` [PATCH v3 09/15] rust/vmstate: Re-implement VMState trait for timer binding Zhao Liu
2025-03-18 13:02 ` [PATCH v3 10/15] rust/vmstate: Support vmstate_validate Zhao Liu
2025-03-18 13:02 ` Zhao Liu [this message]
2025-03-18 13:02 ` [PATCH v3 12/15] rust/vmstate: Add unit test for vmstate_{of|struct} macro Zhao Liu
2025-03-18 13:02 ` [PATCH v3 13/15] rust/vmstate: Add unit test for pointer case Zhao Liu
2025-03-18 13:02 ` [PATCH v3 14/15] rust/vmstate: Add unit test for vmstate_validate Zhao Liu
2025-03-18 13:02 ` [PATCH v3 15/15] rust/vmstate: Include complete crate path of VMStateFlags in vmstate_clock Zhao Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250318130219.1799170-12-zhao1.liu@intel.com \
--to=zhao1.liu@intel.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-rust@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).