summary refs log tree commit diff stats
path: root/rust/qemu-api-macros/src/tests.rs
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-07-14 09:36:57 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2025-07-14 09:36:57 -0400
commitb92b39af4219df4250f121f64d215506909c7404 (patch)
treed112c017e3c77df7341e5fe28072571ad9ecceb8 /rust/qemu-api-macros/src/tests.rs
parent6fae7ce1488e3f5bdcc1747564ea68e7f6f0e931 (diff)
parent5d21ee453ad8e3f95f75e542cb3b35c5bb7cf23a (diff)
downloadfocaccia-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.rs137
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),
+                    }
+                }
+            }
+        }
+    );
+}