1//! Compare libc's CMSG(3) family of functions against the actual C macros, for
2//! various inputs.
3
4extern crate libc;
5
6#[cfg(unix)]
7mod t {
8
9    use libc::{self, c_uchar, c_uint, c_void, cmsghdr, msghdr};
10    use std::mem;
11
12    extern "C" {
13        pub fn cmsg_firsthdr(msgh: *const msghdr) -> *mut cmsghdr;
14        // see below
15        #[cfg(not(target_arch = "sparc64"))]
16        pub fn cmsg_nxthdr(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr;
17        pub fn cmsg_space(length: c_uint) -> usize;
18        pub fn cmsg_len(length: c_uint) -> usize;
19        pub fn cmsg_data(cmsg: *const cmsghdr) -> *mut c_uchar;
20    }
21
22    #[test]
23    fn test_cmsg_data() {
24        for l in 0..128 {
25            let pcmsghdr = l as *const cmsghdr;
26            unsafe {
27                assert_eq!(libc::CMSG_DATA(pcmsghdr), cmsg_data(pcmsghdr));
28            }
29        }
30    }
31
32    #[test]
33    fn test_cmsg_firsthdr() {
34        let mut mhdr: msghdr = unsafe { mem::zeroed() };
35        mhdr.msg_control = 0xdeadbeef as *mut c_void;
36        let pmhdr = &mhdr as *const msghdr;
37        for l in 0..128 {
38            mhdr.msg_controllen = l;
39            unsafe {
40                assert_eq!(libc::CMSG_FIRSTHDR(pmhdr), cmsg_firsthdr(pmhdr));
41            }
42        }
43    }
44
45    #[test]
46    fn test_cmsg_len() {
47        for l in 0..128 {
48            unsafe {
49                assert_eq!(libc::CMSG_LEN(l) as usize, cmsg_len(l));
50            }
51        }
52    }
53
54    // Skip on sparc64
55    // https://github.com/rust-lang/libc/issues/1239
56    #[cfg(not(target_arch = "sparc64"))]
57    #[test]
58    fn test_cmsg_nxthdr() {
59        use std::ptr;
60
61        let mut buffer = [0u8; 256];
62        let mut mhdr: msghdr = unsafe { mem::zeroed() };
63        let pmhdr = &mhdr as *const msghdr;
64        for start_ofs in 0..64 {
65            let pcmsghdr = &mut buffer[start_ofs] as *mut u8 as *mut cmsghdr;
66            mhdr.msg_control = pcmsghdr as *mut c_void;
67            mhdr.msg_controllen = (160 - start_ofs) as _;
68            for cmsg_len in 0..64 {
69                for next_cmsg_len in 0..32 {
70                    for i in buffer[start_ofs..].iter_mut() {
71                        *i = 0;
72                    }
73                    unsafe {
74                        (*pcmsghdr).cmsg_len = cmsg_len;
75                        let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr);
76                        let next = cmsg_nxthdr(pmhdr, pcmsghdr);
77                        assert_eq!(libc_next, next);
78
79                        if libc_next != ptr::null_mut() {
80                            (*libc_next).cmsg_len = next_cmsg_len;
81                            let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr);
82                            let next = cmsg_nxthdr(pmhdr, pcmsghdr);
83                            assert_eq!(libc_next, next);
84                        }
85                    }
86                }
87            }
88        }
89    }
90
91    #[test]
92    fn test_cmsg_space() {
93        unsafe {
94            for l in 0..128 {
95                assert_eq!(libc::CMSG_SPACE(l) as usize, cmsg_space(l));
96            }
97        }
98    }
99}
100