diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-14 09:36:57 -0400 |
|---|---|---|
| committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-14 09:36:57 -0400 |
| commit | b92b39af4219df4250f121f64d215506909c7404 (patch) | |
| tree | d112c017e3c77df7341e5fe28072571ad9ecceb8 /rust/qemu-api-macros/src/tests.rs | |
| parent | 6fae7ce1488e3f5bdcc1747564ea68e7f6f0e931 (diff) | |
| parent | 5d21ee453ad8e3f95f75e542cb3b35c5bb7cf23a (diff) | |
| download | focaccia-qemu-b92b39af4219df4250f121f64d215506909c7404.tar.gz focaccia-qemu-b92b39af4219df4250f121f64d215506909c7404.zip | |
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* rust: miscellaneous fixes * rust: qemu-api-macros: cleanup and add unit tests for TryInto * rust: log: implement io::Write, avoid memory allocations when logging constant strings * target/i386: fix usage of properties whenever accelerators change the default (e.g. vendor) * target/i386: add support for TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT * target/i386: add support for booting an SEV VM from an IGVM file * target/i386: unify cache model descriptions between CPUID 2, CPUID 4 and AMD specific CPUID 0x80000006 * target/i386: introduce cache models for recent Intel CPU models * target/i386: mark some 0x80000000-0x80000008 bits as reserved on Intel * target/i386: cleanups # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmh0v+sUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroOQUQf8CTsCnl2xYrnrkVfSVj6kuAE+JYD6 # oLSXsOEG4yrVknuhwIfVsqNScmleJCdz85ej7CZxy3vzzgjLfmy7nwifKEIKku7E # XO/Q3HbB898MnzqceQRmwe1AzELoj1Lave215CPhUBo60LCRPwaIZsiHprnNZgXi # TyHlmywDVRjyFLtKkx3El0dnLAhFqPWeGh81CD5lPLZZJ+Wt2FuAw2zqSOGB2ztM # FkJmunFJiaTItjyCN/uNvBSbDKecAHgCXvSCVNG3+I4U2R0gK1lcwm3TRo7yKia+ # HUHGa3UEXoIqlRfXdX6zuc8tW1/u6SPv+8WX53t204PAeSWDUrtIe9jZ4A== # =y4/a # -----END PGP SIGNATURE----- # gpg: Signature made Mon 14 Jul 2025 04:29:31 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (77 commits) i386/cpu: Honor maximum value for CPUID.8000001DH.EAX[25:14] i386/cpu: Fix overflow of cache topology fields in CPUID.04H i386/cpu: Fix cpu number overflow in CPUID.01H.EBX[23:16] i386/cpu: Fix number of addressable IDs field for CPUID.01H.EBX[23:16] i386/cpu: Reorder CPUID leaves in cpu_x86_cpuid() tests/vm: bump FreeBSD image to 14.3 tests/functional: test_x86_cpu_model_versions: remove dead tests i386/cpu: Mark CPUID 0x80000008 ECX bits[0:7] & [12:15] as reserved for Intel/Zhaoxin i386/cpu: Mark CPUID 0x80000007[EBX] as reserved for Intel i386/cpu: Mark EBX/ECX/EDX in CPUID 0x80000000 leaf as reserved for Intel i386/cpu: Enable 0x1f leaf for YongFeng by default i386/cpu: Enable 0x1f leaf for SapphireRapids by default i386/cpu: Enable 0x1f leaf for GraniteRapids by default i386/cpu: Enable 0x1f leaf for SierraForest by default i386/cpu: Enable 0x1f leaf for SierraForest by default i386/cpu: Add a "x-force-cpuid-0x1f" property i386/cpu: Introduce cache model for YongFeng i386/cpu: Introduce cache model for SapphireRapids i386/cpu: Introduce cache model for GraniteRapids i386/cpu: Introduce cache model for SierraForest ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'rust/qemu-api-macros/src/tests.rs')
| -rw-r--r-- | rust/qemu-api-macros/src/tests.rs | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/rust/qemu-api-macros/src/tests.rs b/rust/qemu-api-macros/src/tests.rs new file mode 100644 index 0000000000..d6dcd62fcf --- /dev/null +++ b/rust/qemu-api-macros/src/tests.rs @@ -0,0 +1,137 @@ +// Copyright 2025, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use quote::quote; + +use super::*; + +macro_rules! derive_compile_fail { + ($derive_fn:ident, $input:expr, $error_msg:expr) => {{ + let input: proc_macro2::TokenStream = $input; + let error_msg: &str = $error_msg; + let derive_fn: fn(input: syn::DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> = + $derive_fn; + + let input: syn::DeriveInput = syn::parse2(input).unwrap(); + let result = derive_fn(input); + let err = result.unwrap_err().into_compile_error(); + assert_eq!( + err.to_string(), + quote! { ::core::compile_error! { #error_msg } }.to_string() + ); + }}; +} + +macro_rules! derive_compile { + ($derive_fn:ident, $input:expr, $($expected:tt)*) => {{ + let input: proc_macro2::TokenStream = $input; + let expected: proc_macro2::TokenStream = $($expected)*; + let derive_fn: fn(input: syn::DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> = + $derive_fn; + + let input: syn::DeriveInput = syn::parse2(input).unwrap(); + let result = derive_fn(input).unwrap(); + assert_eq!(result.to_string(), expected.to_string()); + }}; +} + +#[test] +fn test_derive_object() { + derive_compile_fail!( + derive_object_or_error, + quote! { + #[derive(Object)] + struct Foo { + _unused: [u8; 0], + } + }, + "#[repr(C)] required for #[derive(Object)]" + ); + derive_compile!( + derive_object_or_error, + quote! { + #[derive(Object)] + #[repr(C)] + struct Foo { + _unused: [u8; 0], + } + }, + quote! { + ::qemu_api::assert_field_type!( + Foo, + _unused, + ::qemu_api::qom::ParentField<<Foo as ::qemu_api::qom::ObjectImpl>::ParentType> + ); + ::qemu_api::module_init! { + MODULE_INIT_QOM => unsafe { + ::qemu_api::bindings::type_register_static(&<Foo as ::qemu_api::qom::ObjectImpl>::TYPE_INFO); + } + } + } + ); +} + +#[test] +fn test_derive_tryinto() { + derive_compile_fail!( + derive_tryinto_or_error, + quote! { + #[derive(TryInto)] + struct Foo { + _unused: [u8; 0], + } + }, + "#[repr(u8/u16/u32/u64) required for #[derive(TryInto)]" + ); + derive_compile!( + derive_tryinto_or_error, + quote! { + #[derive(TryInto)] + #[repr(u8)] + enum Foo { + First = 0, + Second, + } + }, + quote! { + impl Foo { + #[allow(dead_code)] + pub const fn into_bits(self) -> u8 { + self as u8 + } + + #[allow(dead_code)] + pub const fn from_bits(value: u8) -> Self { + match ({ + const First: u8 = Foo::First as u8; + const Second: u8 = Foo::Second as u8; + match value { + First => core::result::Result::Ok(Foo::First), + Second => core::result::Result::Ok(Foo::Second), + _ => core::result::Result::Err(value), + } + }) { + Ok(x) => x, + Err(_) => panic!("invalid value for Foo"), + } + } + } + + impl core::convert::TryFrom<u8> for Foo { + type Error = u8; + + #[allow(ambiguous_associated_items)] + fn try_from(value: u8) -> Result<Self, u8> { + const First: u8 = Foo::First as u8; + const Second: u8 = Foo::Second as u8; + match value { + First => core::result::Result::Ok(Foo::First), + Second => core::result::Result::Ok(Foo::Second), + _ => core::result::Result::Err(value), + } + } + } + } + ); +} |