From 163b09a94f70a48b30a311213d830f7e3feb7195 Mon Sep 17 00:00:00 2001 From: mbyx Date: Sat, 27 Sep 2025 11:09:57 +0500 Subject: [PATCH] ctest: automatically skip roundtrip testing for aliases to arrays --- ctest/src/generator.rs | 4 +--- ctest/src/template.rs | 4 ++++ ctest/tests/basic.rs | 2 +- ctest/tests/input/simple.h | 2 ++ ctest/tests/input/simple.out.with-renames.c | 6 ++++++ ctest/tests/input/simple.out.with-renames.rs | 18 ++++++++++++++++++ ctest/tests/input/simple.rs | 5 ++++- 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ctest/src/generator.rs b/ctest/src/generator.rs index 58383aa2d4352..77e43f72954f0 100644 --- a/ctest/src/generator.rs +++ b/ctest/src/generator.rs @@ -930,8 +930,6 @@ impl TestGenerator { self } - // FIXME(ctest): should arrays be handled differently? - /// Configures whether the ABI roundtrip tests for a type are emitted. /// /// The closure is passed the name of a Rust type and returns whether the @@ -939,7 +937,7 @@ impl TestGenerator { /// /// By default all types undergo ABI roundtrip tests. Arrays cannot undergo /// an ABI roundtrip because they cannot be returned by C functions, and - /// have to be manually skipped here. + /// are automatically skipped. /// /// # Examples /// ```no_run diff --git a/ctest/src/template.rs b/ctest/src/template.rs index 71ffb21ac4fc8..f518200ea6be6 100644 --- a/ctest/src/template.rs +++ b/ctest/src/template.rs @@ -257,6 +257,10 @@ impl TestTemplate { helper: &TranslateHelper, ) -> Result<(), TranslationError> { for alias in helper.filtered_ffi_items.aliases() { + // Arrays cannot be roundtripped, and are automatically skipped. + if let syn::Type::Array(_) = alias.ty { + continue; + } let c_ty = helper.c_type(alias)?; self.add_roundtrip_test(helper, alias.ident(), &[], &c_ty, true); } diff --git a/ctest/tests/basic.rs b/ctest/tests/basic.rs index 960be68223123..b1fce9cb1f116 100644 --- a/ctest/tests/basic.rs +++ b/ctest/tests/basic.rs @@ -101,7 +101,7 @@ fn test_skip_simple() { let (mut gen_, out_dir) = default_generator(1, Some("simple.h")).unwrap(); gen_.skip_const(|c| c.ident() == "B" || c.ident() == "A") .skip_c_enum(|e| e == "Color") - .skip_alias(|a| a.ident() == "Byte") + .skip_alias(|a| a.ident() == "Byte" || a.ident() == "gregset_t") .skip_struct(|s| s.ident() == "Person") .skip_union(|u| u.ident() == "Word") .skip_fn(|f| f.ident() == "calloc") diff --git a/ctest/tests/input/simple.h b/ctest/tests/input/simple.h index 8ab62ac451037..bb706ad38a98b 100644 --- a/ctest/tests/input/simple.h +++ b/ctest/tests/input/simple.h @@ -2,6 +2,8 @@ typedef uint8_t Byte; +typedef unsigned long gregset_t[32]; + Byte byte = 0x42; struct Person diff --git a/ctest/tests/input/simple.out.with-renames.c b/ctest/tests/input/simple.out.with-renames.c index cdb4c348e7a4f..223c1ac205295 100644 --- a/ctest/tests/input/simple.out.with-renames.c +++ b/ctest/tests/input/simple.out.with-renames.c @@ -62,6 +62,12 @@ CTEST_EXTERN uint64_t ctest_size_of__Byte(void) { return sizeof(Byte); } // Return the alignment of a type. CTEST_EXTERN uint64_t ctest_align_of__Byte(void) { return CTEST_ALIGNOF(Byte); } +// Return the size of a type. +CTEST_EXTERN uint64_t ctest_size_of__gregset_t(void) { return sizeof(gregset_t); } + +// Return the alignment of a type. +CTEST_EXTERN uint64_t ctest_align_of__gregset_t(void) { return CTEST_ALIGNOF(gregset_t); } + // Return the size of a type. CTEST_EXTERN uint64_t ctest_size_of__Color(void) { return sizeof(enum Color); } diff --git a/ctest/tests/input/simple.out.with-renames.rs b/ctest/tests/input/simple.out.with-renames.rs index f0ad0bc0676a3..a4d66ac524ce0 100644 --- a/ctest/tests/input/simple.out.with-renames.rs +++ b/ctest/tests/input/simple.out.with-renames.rs @@ -186,6 +186,23 @@ mod generated_tests { check_same(rust_align, c_align, "Byte align"); } + /// Compare the size and alignment of the type in Rust and C, making sure they are the same. + pub fn ctest_size_align_gregset_t() { + extern "C" { + fn ctest_size_of__gregset_t() -> u64; + fn ctest_align_of__gregset_t() -> u64; + } + + let rust_size = size_of::() as u64; + let c_size = unsafe { ctest_size_of__gregset_t() }; + + let rust_align = align_of::() as u64; + let c_align = unsafe { ctest_align_of__gregset_t() }; + + check_same(rust_size, c_size, "gregset_t size"); + check_same(rust_align, c_align, "gregset_t align"); + } + /// Compare the size and alignment of the type in Rust and C, making sure they are the same. pub fn ctest_size_align_Color() { extern "C" { @@ -996,6 +1013,7 @@ fn run_all() { ctest_const_BLUE(); ctest_const_GREEN(); ctest_size_align_Byte(); + ctest_size_align_gregset_t(); ctest_size_align_Color(); ctest_size_align_Person(); ctest_size_align_Word(); diff --git a/ctest/tests/input/simple.rs b/ctest/tests/input/simple.rs index c9fff3d7d6853..8abef29aeef85 100644 --- a/ctest/tests/input/simple.rs +++ b/ctest/tests/input/simple.rs @@ -1,7 +1,10 @@ -use std::ffi::{c_char, c_int, c_void}; +use std::ffi::{c_char, c_int, c_ulong, c_void}; pub type Byte = u8; +// This should be automatically skipped for roundtripping. +pub type gregset_t = [c_ulong; 32]; + #[repr(C)] pub struct Person { pub name: *const c_char,