Skip to content

Commit 4404e4f

Browse files
committed
libc-test: port apple to use ctest-next
1 parent 9428748 commit 4404e4f

File tree

6 files changed

+361
-58
lines changed

6 files changed

+361
-58
lines changed

ctest-next/src/ast/function.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{Abi, BoxStr, Parameter};
55
/// This structure is only used for parsing functions in extern blocks.
66
#[derive(Debug, Clone)]
77
pub struct Fn {
8+
#[expect(unused)]
89
pub(crate) public: bool,
910
#[expect(unused)]
1011
pub(crate) abi: Abi,

ctest-next/src/ast/static_variable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{Abi, BoxStr};
66
/// as a result it does not have a field for storing the expression.
77
#[derive(Debug, Clone)]
88
pub struct Static {
9+
#[expect(unused)]
910
pub(crate) public: bool,
1011
#[expect(unused)]
1112
pub(crate) abi: Abi,

ctest-next/src/ast/union.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use crate::{BoxStr, Field};
33
/// Represents a union defined in Rust.
44
#[derive(Debug, Clone)]
55
pub struct Union {
6-
#[expect(unused)]
76
pub(crate) public: bool,
87
pub(crate) ident: BoxStr,
98
pub(crate) fields: Vec<Field>,

ctest-next/src/generator.rs

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub struct TestGenerator {
4242
verbose_skip: bool,
4343
pub(crate) volatile_items: Vec<VolatileItem>,
4444
array_arg: Option<ArrayArg>,
45-
skip_private: bool,
45+
pub(crate) skip_private: bool,
4646
pub(crate) skip_roundtrip: Option<SkipTest>,
4747
pub(crate) skip_signededness: Option<SkipTest>,
4848
}
@@ -872,8 +872,6 @@ impl TestGenerator {
872872
let mut ffi_items = FfiItems::new();
873873
ffi_items.visit_file(&ast);
874874

875-
self.filter_ffi_items(&mut ffi_items);
876-
877875
let output_directory = self
878876
.out_dir
879877
.clone()
@@ -912,36 +910,37 @@ impl TestGenerator {
912910
Ok(output_file_path)
913911
}
914912

915-
/// Skips entire items such as structs, constants, and aliases from being tested.
916-
///
917-
/// Does not skip specific tests or specific fields. If `skip_private` is true,
918-
/// it will skip tests for all private items.
919-
fn filter_ffi_items(&self, ffi_items: &mut FfiItems) {
920-
let verbose = self.verbose_skip;
921-
922-
macro_rules! filter {
923-
($field:ident, $variant:ident, $label:literal) => {{
924-
let skipped: Vec<_> = ffi_items
925-
.$field
926-
.extract_if(.., |item| {
927-
self.skips.iter().any(|f| f(&MapInput::$variant(item)))
928-
|| (self.skip_private && !item.public)
929-
})
930-
.collect();
931-
if verbose {
932-
skipped
933-
.iter()
934-
.for_each(|item| eprintln!("Skipping {} \"{}\"", $label, item.ident()));
935-
}
936-
}};
937-
}
938-
939-
filter!(aliases, Alias, "alias");
940-
filter!(constants, Const, "const");
941-
filter!(structs, Struct, "struct");
942-
filter!(foreign_functions, Fn, "fn");
943-
filter!(foreign_statics, Static, "static");
944-
}
913+
// /// Skips entire items such as structs, constants, and aliases from being tested.
914+
// ///
915+
// /// Does not skip specific tests or specific fields. If `skip_private` is true,
916+
// /// it will skip tests for all private items.
917+
// fn filter_ffi_items(&self, ffi_items: &mut FfiItems) {
918+
// let verbose = self.verbose_skip;
919+
920+
// macro_rules! filter {
921+
// ($field:ident, $variant:ident, $label:literal) => {{
922+
// let skipped: Vec<_> = ffi_items
923+
// .$field
924+
// .extract_if(.., |item| {
925+
// self.skips.iter().any(|f| f(&MapInput::$variant(item)))
926+
// || (self.skip_private && !item.public)
927+
// })
928+
// .collect();
929+
// if verbose {
930+
// skipped
931+
// .iter()
932+
// .for_each(|item| eprintln!("Skipping {} \"{}\"", $label, item.ident()));
933+
// }
934+
// }};
935+
// }
936+
937+
// filter!(aliases, Alias, "alias");
938+
// filter!(constants, Const, "const");
939+
// filter!(structs, Struct, "struct");
940+
// filter!(unions, Union, "union");
941+
// filter!(foreign_functions, Fn, "fn");
942+
// filter!(foreign_statics, Static, "static");
943+
// }
945944

946945
/// Maps Rust identifiers or types to C counterparts, or defaults to the original name.
947946
pub(crate) fn rty_to_cty<'a>(&self, item: impl Into<MapInput<'a>>) -> String {

ctest-next/src/template.rs

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ impl TestTemplate {
8888
&mut self,
8989
helper: &TranslateHelper,
9090
) -> Result<(), TranslationError> {
91-
for constant in helper.ffi_items.constants() {
91+
let should_skip = |map_input| helper.generator.skips.iter().any(|f| f(&map_input));
92+
93+
for constant in helper.ffi_items.constants().iter().filter(|c| {
94+
!(should_skip(MapInput::Const(c)) || helper.generator.skip_private && !c.public)
95+
}) {
9296
if let syn::Type::Ptr(ptr) = &constant.ty
9397
&& let syn::Type::Path(path) = &*ptr.elem
9498
&& path.path.segments.last().unwrap().ident == "c_char"
@@ -126,7 +130,11 @@ impl TestTemplate {
126130
&mut self,
127131
helper: &TranslateHelper,
128132
) -> Result<(), TranslationError> {
129-
for alias in helper.ffi_items.aliases() {
133+
let should_skip = |map_input| helper.generator.skips.iter().any(|f| f(&map_input));
134+
135+
for alias in helper.ffi_items.aliases().iter().filter(|a| {
136+
!(should_skip(MapInput::Alias(a)) || helper.generator.skip_private && !a.public)
137+
}) {
130138
let item = TestSizeAlign {
131139
test_name: size_align_test_ident(alias.ident()),
132140
id: alias.ident().into(),
@@ -136,7 +144,9 @@ impl TestTemplate {
136144
self.size_align_tests.push(item.clone());
137145
self.test_idents.push(item.test_name);
138146
}
139-
for struct_ in helper.ffi_items.structs() {
147+
for struct_ in helper.ffi_items.structs().iter().filter(|s| {
148+
!(should_skip(MapInput::Struct(s)) || helper.generator.skip_private && !s.public)
149+
}) {
140150
let item = TestSizeAlign {
141151
test_name: size_align_test_ident(struct_.ident()),
142152
id: struct_.ident().into(),
@@ -146,7 +156,9 @@ impl TestTemplate {
146156
self.size_align_tests.push(item.clone());
147157
self.test_idents.push(item.test_name);
148158
}
149-
for union_ in helper.ffi_items.unions() {
159+
for union_ in helper.ffi_items.unions().iter().filter(|u| {
160+
!(should_skip(MapInput::Union(u)) || helper.generator.skip_private && !u.public)
161+
}) {
150162
let item = TestSizeAlign {
151163
test_name: size_align_test_ident(union_.ident()),
152164
id: union_.ident().into(),
@@ -167,7 +179,11 @@ impl TestTemplate {
167179
&mut self,
168180
helper: &TranslateHelper,
169181
) -> Result<(), TranslationError> {
170-
for alias in helper.ffi_items.aliases() {
182+
let should_skip = |map_input| helper.generator.skips.iter().any(|f| f(&map_input));
183+
184+
for alias in helper.ffi_items.aliases().iter().filter(|a| {
185+
!(should_skip(MapInput::Alias(a)) || helper.generator.skip_private && !a.public)
186+
}) {
171187
let should_skip_signededness_test = helper
172188
.generator
173189
.skip_signededness
@@ -206,7 +222,10 @@ impl TestTemplate {
206222
.iter()
207223
.flat_map(|struct_| struct_.fields.iter().map(move |field| (struct_, field)))
208224
.filter(|(struct_, field)| {
209-
!should_skip(MapInput::StructField(struct_, field)) && field.public
225+
!(should_skip(MapInput::StructField(struct_, field))
226+
|| should_skip(MapInput::Struct(struct_))
227+
|| !field.public
228+
|| helper.generator.skip_private && !struct_.public)
210229
})
211230
.map(|(struct_, field)| {
212231
(
@@ -222,7 +241,10 @@ impl TestTemplate {
222241
.iter()
223242
.flat_map(|union_| union_.fields.iter().map(move |field| (union_, field)))
224243
.filter(|(union_, field)| {
225-
!should_skip(MapInput::UnionField(union_, field)) && field.public
244+
!(should_skip(MapInput::UnionField(union_, field))
245+
|| should_skip(MapInput::Union(union_))
246+
|| !field.public
247+
|| helper.generator.skip_private && !union_.public)
226248
})
227249
.map(|(union_, field)| {
228250
(
@@ -255,15 +277,23 @@ impl TestTemplate {
255277
&mut self,
256278
helper: &TranslateHelper,
257279
) -> Result<(), TranslationError> {
258-
for alias in helper.ffi_items.aliases() {
280+
let should_skip = |map_input| helper.generator.skips.iter().any(|f| f(&map_input));
281+
282+
for alias in helper.ffi_items.aliases().iter().filter(|a| {
283+
!(should_skip(MapInput::Alias(a)) || helper.generator.skip_private && !a.public)
284+
}) {
259285
let c_ty = helper.c_type(alias)?;
260286
self.add_roundtrip_test(helper, alias.ident(), &[], &c_ty, true);
261287
}
262-
for struct_ in helper.ffi_items.structs() {
288+
for struct_ in helper.ffi_items.structs().iter().filter(|s| {
289+
!(should_skip(MapInput::Struct(s)) || helper.generator.skip_private && !s.public)
290+
}) {
263291
let c_ty = helper.c_type(struct_)?;
264292
self.add_roundtrip_test(helper, struct_.ident(), &struct_.fields, &c_ty, false);
265293
}
266-
for union_ in helper.ffi_items.unions() {
294+
for union_ in helper.ffi_items.unions().iter().filter(|u| {
295+
!(should_skip(MapInput::Union(u)) || helper.generator.skip_private && !u.public)
296+
}) {
267297
let c_ty = helper.c_type(union_)?;
268298
self.add_roundtrip_test(helper, union_.ident(), &union_.fields, &c_ty, false);
269299
}
@@ -312,9 +342,11 @@ impl TestTemplate {
312342
.iter()
313343
.flat_map(|s| s.fields.iter().map(move |f| (s, f)))
314344
.filter(|(s, f)| {
315-
!should_skip(MapInput::StructField(s, f))
316-
&& !should_skip(MapInput::StructFieldType(s, f))
317-
&& f.public
345+
!(should_skip(MapInput::StructField(s, f))
346+
|| should_skip(MapInput::StructFieldType(s, f))
347+
|| should_skip(MapInput::Struct(s))
348+
|| !f.public
349+
|| helper.generator.skip_private && !s.public)
318350
})
319351
.map(|(s, f)| {
320352
(
@@ -341,9 +373,11 @@ impl TestTemplate {
341373
.iter()
342374
.flat_map(|u| u.fields.iter().map(move |f| (u, f)))
343375
.filter(|(u, f)| {
344-
!should_skip(MapInput::UnionField(u, f))
345-
&& !should_skip(MapInput::UnionFieldType(u, f))
346-
&& f.public
376+
!(should_skip(MapInput::UnionField(u, f))
377+
|| should_skip(MapInput::UnionFieldType(u, f))
378+
|| should_skip(MapInput::Union(u))
379+
|| !f.public
380+
|| helper.generator.skip_private && !u.public)
347381
})
348382
.map(|(u, f)| {
349383
(
@@ -536,7 +570,7 @@ impl<'a> TranslateHelper<'a> {
536570
MapInput::Type(_) => panic!("MapInput::Type is not allowed!"),
537571
};
538572

539-
let item = if self.ffi_items.contains_struct(ident) {
573+
let item = if self.ffi_items.contains_struct(&ty) {
540574
MapInput::StructType(&ty)
541575
} else if self.ffi_items.contains_union(ident) {
542576
MapInput::UnionType(&ty)
@@ -554,21 +588,30 @@ impl<'a> TranslateHelper<'a> {
554588
fn basic_c_type(&self, ty: &syn::Type) -> Result<String, TranslationError> {
555589
let type_name = match ty {
556590
syn::Type::Path(p) => p.path.segments.last().unwrap().ident.to_string(),
557-
syn::Type::Ptr(p) => self.basic_c_type(&p.elem)?,
558-
syn::Type::Reference(r) => self.basic_c_type(&r.elem)?,
591+
// Using recursion here causes breakage.
592+
// FIXME(ctest): Might be possible to extract this part into a function.
593+
syn::Type::Ptr(p) => match p.elem.deref() {
594+
syn::Type::Path(p) => p.path.segments.last().unwrap().ident.to_string(),
595+
_ => p.to_token_stream().to_string(),
596+
},
597+
syn::Type::Reference(r) => match r.elem.deref() {
598+
syn::Type::Path(p) => p.path.segments.last().unwrap().ident.to_string(),
599+
_ => r.to_token_stream().to_string(),
600+
},
559601
_ => ty.to_token_stream().to_string(),
560602
};
561603

562604
let unmapped_c_type = self.translator.translate_type(ty)?;
563605
let item = if self.ffi_items.contains_struct(&type_name) {
564-
MapInput::StructType(&unmapped_c_type)
606+
MapInput::StructType(&type_name)
565607
} else if self.ffi_items.contains_union(&type_name) {
566-
MapInput::UnionType(&unmapped_c_type)
608+
MapInput::UnionType(&type_name)
567609
} else {
568-
MapInput::Type(&unmapped_c_type)
610+
MapInput::Type(&type_name)
569611
};
570612

571-
Ok(self.generator.rty_to_cty(item))
613+
let mapped_type = self.generator.rty_to_cty(item.clone());
614+
Ok(unmapped_c_type.replace(&type_name, &mapped_type))
572615
}
573616

574617
/// Partially translate a Rust bare function type into its equivalent C type.

0 commit comments

Comments
 (0)