Test struct field offsets/sizes
This commit is contained in:
parent
a9adfbf56c
commit
3e5155b345
@ -109,13 +109,11 @@ fn build_cfg(cfg: &mut ast::CrateConfig, target: &str) {
|
||||
impl<'a> TestGenerator<'a> {
|
||||
fn test_type(&mut self, ty: &str) {
|
||||
let cty = if ty.starts_with("c_") {
|
||||
let rest = ty[2..].replace("long", " long");
|
||||
if rest.starts_with("u") {
|
||||
format!("unsigned {}", &rest[1..])
|
||||
} else if rest.starts_with("s") && rest != "short" {
|
||||
format!("signed {}", &rest[1..])
|
||||
} else {
|
||||
rest
|
||||
match &ty[2..].replace("long", " long")[..] {
|
||||
s if s.starts_with("u") => format!("unsigned {}", &s[1..]),
|
||||
"short" => format!("short"),
|
||||
s if s.starts_with("s") => format!("signed {}", &s[1..]),
|
||||
s => s.to_string(),
|
||||
}
|
||||
} else {
|
||||
(match ty {
|
||||
@ -126,15 +124,61 @@ impl<'a> TestGenerator<'a> {
|
||||
self.test_size_align(ty, &cty);
|
||||
}
|
||||
|
||||
fn test_struct(&mut self, ty: &str, _s: &ast::StructDef) {
|
||||
let cty = if ty.starts_with("pthread") || ty == "glob_t" {
|
||||
ty.to_string()
|
||||
} else if ty == "ip6_mreq" {
|
||||
"struct ipv6_mreq".to_string()
|
||||
} else {
|
||||
format!("struct {}", ty)
|
||||
fn test_struct(&mut self, ty: &str, s: &ast::StructDef) {
|
||||
let cty = match ty {
|
||||
t if ty.starts_with("pthread") => t.to_string(),
|
||||
"glob_t" => "glob_t".to_string(),
|
||||
"ip6_mreq" => "struct ipv6_mreq".to_string(),
|
||||
s => format!("struct {}", s),
|
||||
};
|
||||
self.test_size_align(ty, &cty);
|
||||
|
||||
writeln!(self.rust, r#"
|
||||
#[test]
|
||||
fn field_offset_size_{ty}() {{
|
||||
"#, ty = ty);
|
||||
for field in s.fields.iter() {
|
||||
let name = match field.node.kind {
|
||||
ast::NamedField(name, ast::Public) => name,
|
||||
ast::NamedField(_, ast::Inherited) => continue,
|
||||
ast::UnnamedField(..) => panic!("no tuple structs in FFI"),
|
||||
};
|
||||
|
||||
let cname = match &name.to_string()[..] {
|
||||
s if s.ends_with("_nsec") && ty == "stat" => {
|
||||
s.replace("_nsec", "spec.tv_nsec")
|
||||
}
|
||||
s => s.to_string(),
|
||||
};
|
||||
|
||||
writeln!(self.c, r#"
|
||||
uint64_t __test_offset_{ty}_{rust_field}() {{
|
||||
return offsetof({cty}, {c_field});
|
||||
}}
|
||||
uint64_t __test_size_{ty}_{rust_field}() {{
|
||||
{cty}* foo = NULL;
|
||||
return sizeof(foo->{c_field});
|
||||
}}
|
||||
"#, ty = ty, cty = cty, rust_field = name, c_field = cname);
|
||||
writeln!(self.rust, r#"
|
||||
extern {{
|
||||
fn __test_offset_{ty}_{field}() -> u64;
|
||||
fn __test_size_{ty}_{field}() -> u64;
|
||||
}}
|
||||
unsafe {{
|
||||
let foo = 0 as *const {ty};
|
||||
same(offset_of!({ty}, {field}),
|
||||
__test_offset_{ty}_{field}(),
|
||||
"field offset {field} of {ty}");
|
||||
same(mem::size_of_val(&(*foo).{field}) as u64,
|
||||
__test_size_{ty}_{field}(),
|
||||
"field size {field} of {ty}");
|
||||
}}
|
||||
"#, ty = ty, field = name);
|
||||
}
|
||||
writeln!(self.rust, r#"
|
||||
}}
|
||||
"#);
|
||||
}
|
||||
|
||||
fn test_size_align(&mut self, rust: &str, c: &str) {
|
||||
@ -150,12 +194,10 @@ impl<'a> TestGenerator<'a> {
|
||||
fn __test_align_{ty}() -> u64;
|
||||
}}
|
||||
unsafe {{
|
||||
let a = mem::size_of::<{ty}>() as u64;
|
||||
let b = __test_size_{ty}();
|
||||
assert!(a == b, "bad size: rust {{}} != c {{}}", a, b);
|
||||
let a = mem::align_of::<{ty}>() as u64;
|
||||
let b = __test_align_{ty}();
|
||||
assert!(a == b, "bad align: rust {{}} != c {{}}", a, b);
|
||||
same(mem::size_of::<{ty}>() as u64,
|
||||
__test_size_{ty}(), "size");
|
||||
same(mem::align_of::<{ty}>() as u64,
|
||||
__test_align_{ty}(), "align");
|
||||
}}
|
||||
}}
|
||||
"#, ty = rust);
|
||||
|
@ -6,5 +6,17 @@ use std::mem;
|
||||
use libc::*;
|
||||
use libc::types::os::common::bsd43::*;
|
||||
|
||||
fn same(rust: u64, c: u64, attr: &str) {
|
||||
if rust != c {
|
||||
panic!("bad {}: rust: {} != c {}", attr, rust, c);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! offset_of {
|
||||
($ty:ident, $field:ident) => (
|
||||
(&((*(0 as *const $ty)).$field)) as *const _ as u64
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
include!(concat!(env!("OUT_DIR"), "/all.rs"));
|
||||
|
100
src/lib.rs
100
src/lib.rs
@ -230,11 +230,11 @@ pub mod types {
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
pub gl_offs: size_t,
|
||||
|
||||
pub __unused1: *mut c_void,
|
||||
pub __unused2: *mut c_void,
|
||||
pub __unused3: *mut c_void,
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
__unused1: *mut c_void,
|
||||
__unused2: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -491,8 +491,8 @@ pub mod types {
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused4: c_long,
|
||||
pub __unused5: c_long,
|
||||
__unused4: c_long,
|
||||
__unused5: c_long,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -693,7 +693,7 @@ pub mod types {
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_long; 3],
|
||||
__unused: [c_long; 3],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -738,7 +738,7 @@ pub mod types {
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_int; 2],
|
||||
__unused: [c_int; 2],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -787,18 +787,18 @@ pub mod types {
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)] pub struct glob_t {
|
||||
pub gl_pathc: size_t,
|
||||
pub __unused1: size_t,
|
||||
__unused1: size_t,
|
||||
pub gl_offs: size_t,
|
||||
pub __unused2: c_int,
|
||||
__unused2: c_int,
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
|
||||
pub __unused3: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
pub __unused6: *mut c_void,
|
||||
pub __unused7: *mut c_void,
|
||||
pub __unused8: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
__unused6: *mut c_void,
|
||||
__unused7: *mut c_void,
|
||||
__unused8: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -1021,7 +1021,7 @@ pub mod types {
|
||||
pub st_lspare: int32_t,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
pub __unused: [u8; 8],
|
||||
__unused: [u8; 8],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -1149,18 +1149,18 @@ pub mod types {
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)] pub struct glob_t {
|
||||
pub gl_pathc: size_t,
|
||||
pub __unused1: size_t,
|
||||
__unused1: size_t,
|
||||
pub gl_offs: size_t,
|
||||
pub __unused2: c_int,
|
||||
__unused2: c_int,
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
|
||||
pub __unused3: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
pub __unused6: *mut c_void,
|
||||
pub __unused7: *mut c_void,
|
||||
pub __unused8: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
__unused6: *mut c_void,
|
||||
__unused7: *mut c_void,
|
||||
__unused8: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -1422,32 +1422,32 @@ pub mod types {
|
||||
pub gl_offs: c_int,
|
||||
pub gl_flags: c_int,
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
pub __unused1: *mut c_void,
|
||||
pub __unused2: *mut c_void,
|
||||
pub __unused3: *mut c_void,
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
pub __unused6: *mut c_void,
|
||||
pub __unused7: *mut c_void,
|
||||
__unused1: *mut c_void,
|
||||
__unused2: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
__unused6: *mut c_void,
|
||||
__unused7: *mut c_void,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "netbsd", target_os="openbsd"))]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)] pub struct glob_t {
|
||||
pub gl_pathc: c_int,
|
||||
pub __unused1: c_int,
|
||||
__unused1: c_int,
|
||||
pub gl_offs: c_int,
|
||||
pub __unused2: c_int,
|
||||
__unused2: c_int,
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
|
||||
pub __unused3: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
pub __unused6: *mut c_void,
|
||||
pub __unused7: *mut c_void,
|
||||
pub __unused8: *mut c_void,
|
||||
pub __unused9: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
__unused6: *mut c_void,
|
||||
__unused7: *mut c_void,
|
||||
__unused8: *mut c_void,
|
||||
__unused9: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -2122,18 +2122,18 @@ pub mod types {
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)] pub struct glob_t {
|
||||
pub gl_pathc: size_t,
|
||||
pub __unused1: c_int,
|
||||
__unused1: c_int,
|
||||
pub gl_offs: size_t,
|
||||
pub __unused2: c_int,
|
||||
__unused2: c_int,
|
||||
pub gl_pathv: *mut *mut c_char,
|
||||
|
||||
pub __unused3: *mut c_void,
|
||||
__unused3: *mut c_void,
|
||||
|
||||
pub __unused4: *mut c_void,
|
||||
pub __unused5: *mut c_void,
|
||||
pub __unused6: *mut c_void,
|
||||
pub __unused7: *mut c_void,
|
||||
pub __unused8: *mut c_void,
|
||||
__unused4: *mut c_void,
|
||||
__unused5: *mut c_void,
|
||||
__unused6: *mut c_void,
|
||||
__unused7: *mut c_void,
|
||||
__unused8: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
Loading…
Reference in New Issue
Block a user