/* This file was autogenerated by ctest; do not modify directly */

/// As this file is sometimes built using rustc, crate level attributes
/// are not allowed at the top-level, so we hack around this by keeping it
/// inside of a module.
mod generated_tests {
    #![allow(non_snake_case)]
    // FIXME: rustc raises this lint on `#[non_exhaustive]` structs, even via a pointer. Once
    // this is fixed we should deny it.
    #![allow(improper_ctypes)]
    #![deny(improper_ctypes_definitions)]
    #[allow(unused_imports)]
    use std::ffi::{CStr, c_int, c_char, c_uint};
    use std::fmt::{Debug, Write};
    use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
    #[allow(unused_imports)]
    use std::{mem, ptr, slice};
    #[allow(unused_imports)]
    use std::mem::{MaybeUninit, offset_of};

    use super::*;

    pub static FAILED: AtomicBool = AtomicBool::new(false);
    pub static NTESTS: AtomicUsize = AtomicUsize::new(0);

    /// Check that the value returned from the Rust and C side in a certain test is equivalent.
    ///
    /// Internally it will remember which checks failed and how many tests have been run.
    fn check_same<T: PartialEq + Debug>(rust: T, c: T, attr: &str) {
        if rust != c {
            eprintln!("bad {attr}: rust: {rust:?} != c {c:?}");
            FAILED.store(true, Ordering::Relaxed);
        } else {
            NTESTS.fetch_add(1, Ordering::Relaxed);
        }
    }

    fn check_same_bytes(rust: &[u8], c: &[u8], attr: &str) {
        if rust == c {
            NTESTS.fetch_add(1, Ordering::Relaxed);
            return;
        }

        FAILED.store(true, Ordering::Relaxed);
        // Buffer to a string so we don't write individual bytes to stdio
        let mut s = String::new();
        if rust.len() == c.len() {
            for (i, (&rb, &cb)) in rust.iter().zip(c.iter()).enumerate() {
                if rb != cb {
                    writeln!(
                        s, "bad {attr} at byte {i}: rust: {rb:?} ({rb:#x}) != c {cb:?} ({cb:#x})"
                    ).unwrap();
                    break;
                }
            }
        } else {
            writeln!(s, "bad {attr}: rust len {} != c len {}", rust.len(), c.len()).unwrap();
        }

        write!(s, "    rust bytes:").unwrap();
        for b in rust {
            write!(s, " {b:02x}").unwrap();
        }
        write!(s, "\n    c bytes:   ").unwrap();
        for b in c {
            write!(s, " {b:02x}").unwrap();
        }
        eprintln!("{s}");
    }


/* Test that the string constant is the same in both Rust and C.
 * While fat pointers can't be translated, we instead use * const c_char.
 */

    pub fn ctest_const_cstr_A() {
        extern "C" {
            fn ctest_const_cstr__A() -> *const c_char;
        }

        
        let r_val = unsafe {
            let r_ptr: *const c_char = A;
            assert!(!r_ptr.is_null(), "const `A` is null");
            CStr::from_ptr(r_ptr)
        };

        
        let c_val = unsafe {
            let c_ptr: *const c_char = ctest_const_cstr__A();
            CStr::from_ptr(c_ptr)
        };

        check_same(r_val, c_val, "const `A` string");
    }

    pub fn ctest_const_cstr_B() {
        extern "C" {
            fn ctest_const_cstr__B() -> *const c_char;
        }

        
        let r_val = unsafe {
            let r_ptr: *const c_char = B;
            assert!(!r_ptr.is_null(), "const `B` is null");
            CStr::from_ptr(r_ptr)
        };

        
        let c_val = unsafe {
            let c_ptr: *const c_char = ctest_const_cstr__B();
            CStr::from_ptr(c_ptr)
        };

        check_same(r_val, c_val, "const `B` string");
    }


/* Test that the value of the constant is the same in both Rust and C.
 *
 * This performs a byte by byte comparison of the constant value.
 */

    pub fn ctest_const_RED() {
        type T = Color;
        extern "C" {
            fn ctest_const__RED() -> *const T;
        }

        

        let r_val: T = RED;
        let r_bytes = unsafe {
            slice::from_raw_parts(ptr::from_ref(&r_val).cast::<u8>(), size_of::<T>())
        };

        let c_bytes = unsafe {
            let c_ptr: *const T = ctest_const__RED();
            slice::from_raw_parts(c_ptr.cast::<u8>(), size_of::<T>())
        };

        check_same_bytes(r_bytes, c_bytes, "`RED` value");
    }

    pub fn ctest_const_BLUE() {
        type T = Color;
        extern "C" {
            fn ctest_const__BLUE() -> *const T;
        }

        

        let r_val: T = BLUE;
        let r_bytes = unsafe {
            slice::from_raw_parts(ptr::from_ref(&r_val).cast::<u8>(), size_of::<T>())
        };

        let c_bytes = unsafe {
            let c_ptr: *const T = ctest_const__BLUE();
            slice::from_raw_parts(c_ptr.cast::<u8>(), size_of::<T>())
        };

        check_same_bytes(r_bytes, c_bytes, "`BLUE` value");
    }

    pub fn ctest_const_GREEN() {
        type T = Color;
        extern "C" {
            fn ctest_const__GREEN() -> *const T;
        }

        

        let r_val: T = GREEN;
        let r_bytes = unsafe {
            slice::from_raw_parts(ptr::from_ref(&r_val).cast::<u8>(), size_of::<T>())
        };

        let c_bytes = unsafe {
            let c_ptr: *const T = ctest_const__GREEN();
            slice::from_raw_parts(c_ptr.cast::<u8>(), size_of::<T>())
        };

        check_same_bytes(r_bytes, c_bytes, "`GREEN` value");
    }


/* Compare the size and alignment of the type in Rust and C, making sure they are the same. */

    pub fn ctest_size_align_Byte() {
        extern "C" {
            fn ctest_size_of__Byte() -> u64;
            fn ctest_align_of__Byte() -> u64;
        }

        let rust_size = size_of::<Byte>() as u64;
        let c_size = unsafe { ctest_size_of__Byte() };

        let rust_align = align_of::<Byte>() as u64;
        let c_align = unsafe { ctest_align_of__Byte() };

        check_same(rust_size, c_size, "`Byte` size");
        check_same(rust_align, c_align, "`Byte` align");
    }

    pub fn ctest_size_align_volatile_char() {
        extern "C" {
            fn ctest_size_of__volatile_char() -> u64;
            fn ctest_align_of__volatile_char() -> u64;
        }

        let rust_size = size_of::<volatile_char>() as u64;
        let c_size = unsafe { ctest_size_of__volatile_char() };

        let rust_align = align_of::<volatile_char>() as u64;
        let c_align = unsafe { ctest_align_of__volatile_char() };

        check_same(rust_size, c_size, "`volatile_char` size");
        check_same(rust_align, c_align, "`volatile_char` align");
    }

    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::<gregset_t>() as u64;
        let c_size = unsafe { ctest_size_of__gregset_t() };

        let rust_align = align_of::<gregset_t>() 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");
    }

    pub fn ctest_size_align_Color() {
        extern "C" {
            fn ctest_size_of__Color() -> u64;
            fn ctest_align_of__Color() -> u64;
        }

        let rust_size = size_of::<Color>() as u64;
        let c_size = unsafe { ctest_size_of__Color() };

        let rust_align = align_of::<Color>() as u64;
        let c_align = unsafe { ctest_align_of__Color() };

        check_same(rust_size, c_size, "`Color` size");
        check_same(rust_align, c_align, "`Color` align");
    }

    pub fn ctest_size_align_Person() {
        extern "C" {
            fn ctest_size_of__Person() -> u64;
            fn ctest_align_of__Person() -> u64;
        }

        let rust_size = size_of::<Person>() as u64;
        let c_size = unsafe { ctest_size_of__Person() };

        let rust_align = align_of::<Person>() as u64;
        let c_align = unsafe { ctest_align_of__Person() };

        check_same(rust_size, c_size, "`Person` size");
        check_same(rust_align, c_align, "`Person` align");
    }

    pub fn ctest_size_align_Word() {
        extern "C" {
            fn ctest_size_of__Word() -> u64;
            fn ctest_align_of__Word() -> u64;
        }

        let rust_size = size_of::<Word>() as u64;
        let c_size = unsafe { ctest_size_of__Word() };

        let rust_align = align_of::<Word>() as u64;
        let c_align = unsafe { ctest_align_of__Word() };

        check_same(rust_size, c_size, "`Word` size");
        check_same(rust_align, c_align, "`Word` align");
    }


/* Make sure that the signededness of a type alias in Rust and C is the same.
 *
 * This is done by casting 0 to that type and flipping all of its bits. For unsigned types,
 * this would result in a value larger than zero. For signed types, this results in a value
 * smaller than 0.
 */

    pub fn ctest_signededness_Byte() {
        extern "C" {
            fn ctest_signededness_of__Byte() -> u32;
        }
        let all_ones = !(0 as Byte);
        let all_zeros = 0 as Byte;
        let c_is_signed = unsafe { ctest_signededness_of__Byte() };

        check_same((all_ones < all_zeros) as u32, c_is_signed, "`Byte` signed");
    }

    pub fn ctest_signededness_volatile_char() {
        extern "C" {
            fn ctest_signededness_of__volatile_char() -> u32;
        }
        let all_ones = !(0 as volatile_char);
        let all_zeros = 0 as volatile_char;
        let c_is_signed = unsafe { ctest_signededness_of__volatile_char() };

        check_same((all_ones < all_zeros) as u32, c_is_signed, "`volatile_char` signed");
    }


/* Make sure that the offset and size of a field in a struct/union is the same. */

    pub fn ctest_field_size_offset_Person_name() {
        extern "C" {
            fn ctest_offset_of__Person__name() -> u64;
            fn ctest_size_of__Person__name() -> u64;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).name   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Person__name() };
        check_same(offset_of!(Person, name) as u64, ctest_field_offset,
            "field offset `name` of `Person`");
        
        let ctest_field_size = unsafe { ctest_size_of__Person__name() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `name` of `Person`");
    }

    pub fn ctest_field_size_offset_Person_age() {
        extern "C" {
            fn ctest_offset_of__Person__age() -> u64;
            fn ctest_size_of__Person__age() -> u64;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).age   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Person__age() };
        check_same(offset_of!(Person, age) as u64, ctest_field_offset,
            "field offset `age` of `Person`");
        
        let ctest_field_size = unsafe { ctest_size_of__Person__age() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `age` of `Person`");
    }

    pub fn ctest_field_size_offset_Person_job() {
        extern "C" {
            fn ctest_offset_of__Person__job() -> u64;
            fn ctest_size_of__Person__job() -> u64;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).job   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Person__job() };
        check_same(offset_of!(Person, job) as u64, ctest_field_offset,
            "field offset `job` of `Person`");
        
        let ctest_field_size = unsafe { ctest_size_of__Person__job() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `job` of `Person`");
    }

    pub fn ctest_field_size_offset_Person_favorite_color() {
        extern "C" {
            fn ctest_offset_of__Person__favorite_color() -> u64;
            fn ctest_size_of__Person__favorite_color() -> u64;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).favorite_color   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Person__favorite_color() };
        check_same(offset_of!(Person, favorite_color) as u64, ctest_field_offset,
            "field offset `favorite_color` of `Person`");
        
        let ctest_field_size = unsafe { ctest_size_of__Person__favorite_color() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `favorite_color` of `Person`");
    }

    pub fn ctest_field_size_offset_Word_word() {
        extern "C" {
            fn ctest_offset_of__Word__word() -> u64;
            fn ctest_size_of__Word__word() -> u64;
        }

        let uninit_ty = MaybeUninit::<Word>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).word   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Word__word() };
        check_same(offset_of!(Word, word) as u64, ctest_field_offset,
            "field offset `word` of `Word`");
        
        let ctest_field_size = unsafe { ctest_size_of__Word__word() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `word` of `Word`");
    }

    pub fn ctest_field_size_offset_Word_byte() {
        extern "C" {
            fn ctest_offset_of__Word__byte() -> u64;
            fn ctest_size_of__Word__byte() -> u64;
        }

        let uninit_ty = MaybeUninit::<Word>::zeroed();
        let uninit_ty = uninit_ty.as_ptr();

        
        let ty_ptr = unsafe { &raw const (*uninit_ty).byte   };
        
        let val = unsafe { ty_ptr.read_unaligned() };

        
        let ctest_field_offset = unsafe { ctest_offset_of__Word__byte() };
        check_same(offset_of!(Word, byte) as u64, ctest_field_offset,
            "field offset `byte` of `Word`");
        
        let ctest_field_size = unsafe { ctest_size_of__Word__byte() };
        check_same(size_of_val(&val) as u64, ctest_field_size,
            "field size `byte` of `Word`");
    }


/* Tests if the pointer to the field is the same in Rust and C. */

    pub fn ctest_field_ptr_Person_name() {
        extern "C" {
            fn ctest_field_ptr__Person__name(a: *const Person) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).name) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Person__name(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `name` of `Person`");
    }

    pub fn ctest_field_ptr_Person_age() {
        extern "C" {
            fn ctest_field_ptr__Person__age(a: *const Person) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).age) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Person__age(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `age` of `Person`");
    }

    pub fn ctest_field_ptr_Person_job() {
        extern "C" {
            fn ctest_field_ptr__Person__job(a: *const Person) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).job) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Person__job(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `job` of `Person`");
    }

    pub fn ctest_field_ptr_Person_favorite_color() {
        extern "C" {
            fn ctest_field_ptr__Person__favorite_color(a: *const Person) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Person>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).favorite_color) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Person__favorite_color(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `favorite_color` of `Person`");
    }

    pub fn ctest_field_ptr_Word_word() {
        extern "C" {
            fn ctest_field_ptr__Word__word(a: *const Word) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Word>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).word) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Word__word(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `word` of `Word`");
    }

    pub fn ctest_field_ptr_Word_byte() {
        extern "C" {
            fn ctest_field_ptr__Word__byte(a: *const Word) -> *mut u8;
        }

        let uninit_ty = MaybeUninit::<Word>::zeroed();
        let ty_ptr = uninit_ty.as_ptr();
        // SAFETY: We don't read `field_ptr`, only compare the pointer itself.
        // The assumption is made that this does not wrap the address space.
        let field_ptr = unsafe { &raw const ((*ty_ptr).byte) };

        // SAFETY: FFI call with no preconditions
        let ctest_field_ptr = unsafe { ctest_field_ptr__Word__byte(ty_ptr) };
        check_same(field_ptr.cast(), ctest_field_ptr,
            "field pointer access `byte` of `Word`");
    }

/* Generates a padding map for a specific type.
 *
 * Essentially, it returns a list of bytes, whose length is equal to the size of the type in
 * bytes. Each element corresponds to a byte and has two values. `true` if the byte is padding,
 * and `false` if the byte is not padding.
 *
 * For aliases we assume that there are no padding bytes, for structs and unions,
 * if there are no fields, then everything is padding, if there are fields, then we have to
 * go through each field and figure out the padding.
 */

    fn roundtrip_padding__Byte() -> Vec<bool> {
        if 0 == 0 {
            
            return vec![!true; size_of::<Byte>()]
        }

        
        #[allow(unused_mut)]
        let mut v = Vec::<(usize, usize)>::new();
        #[allow(unused_variables)]
        let bar = MaybeUninit::<Byte>::zeroed();
        #[allow(unused_variables)]
        let bar = bar.as_ptr();
        
        let mut is_padding_byte = vec![true; size_of::<Byte>()];
        for (off, size) in &v {
            for i in 0..*size {
                is_padding_byte[off + i] = false;
            }
        }
        is_padding_byte
    }

    
    pub fn ctest_roundtrip_Byte() {
        type U = Byte;
        extern "C" {
            fn ctest_size_of__Byte() -> u64;
            fn ctest_roundtrip__Byte(
                input: MaybeUninit<U>, is_padding_byte: *const bool, value_bytes: *mut u8
            ) -> U;
        }

        const SIZE: usize = size_of::<U>();

        let is_padding_byte = roundtrip_padding__Byte();
        let mut expected = vec![0u8; SIZE];
        let mut input = MaybeUninit::<U>::zeroed();

        let input_ptr = input.as_mut_ptr().cast::<u8>();

        
        for i in 0..SIZE {
            let c: u8 = (i % 256) as u8;
            let c = if c == 0 { 42 } else { c };
            let d: u8 = 255_u8 - (i % 256) as u8;
            let d = if d == 0 { 42 } else { d };
            unsafe {
                input_ptr.add(i).write_volatile(c);
                expected[i] = d;
            }
        }

        let c_size = unsafe { ctest_size_of__Byte() } as usize;
        if SIZE != c_size {
            FAILED.store(true, Ordering::Relaxed);
            eprintln!(
                "size of `Byte` is {c_size} in C and {SIZE} in Rust\n",
            );
            return;
        }

        let mut c_value_bytes = vec![0; size_of::<Byte>()];
        let r: U = unsafe {
            ctest_roundtrip__Byte(input, is_padding_byte.as_ptr(), c_value_bytes.as_mut_ptr())
        };

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = unsafe { *input_ptr.add(i) };
            let c = c_value_bytes[i];
            if rust != c {
                eprintln!("rust[{}] = {} != {} (C): Rust `Byte` -> C", i, rust, c);
                FAILED.store(true, Ordering::Relaxed);
            }
        }

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = expected[i] as usize;
            let c = unsafe { (&raw const r).cast::<u8>().add(i).read_volatile() as usize };
            if rust != c {
                eprintln!(
                    "rust [{i}] = {rust} != {c} (C): C `Byte` -> Rust",
                );
                FAILED.store(true, Ordering::Relaxed);
            }
        }
    }

    fn roundtrip_padding__volatile_char() -> Vec<bool> {
        if 0 == 0 {
            
            return vec![!true; size_of::<volatile_char>()]
        }

        
        #[allow(unused_mut)]
        let mut v = Vec::<(usize, usize)>::new();
        #[allow(unused_variables)]
        let bar = MaybeUninit::<volatile_char>::zeroed();
        #[allow(unused_variables)]
        let bar = bar.as_ptr();
        
        let mut is_padding_byte = vec![true; size_of::<volatile_char>()];
        for (off, size) in &v {
            for i in 0..*size {
                is_padding_byte[off + i] = false;
            }
        }
        is_padding_byte
    }

    
    pub fn ctest_roundtrip_volatile_char() {
        type U = volatile_char;
        extern "C" {
            fn ctest_size_of__volatile_char() -> u64;
            fn ctest_roundtrip__volatile_char(
                input: MaybeUninit<U>, is_padding_byte: *const bool, value_bytes: *mut u8
            ) -> U;
        }

        const SIZE: usize = size_of::<U>();

        let is_padding_byte = roundtrip_padding__volatile_char();
        let mut expected = vec![0u8; SIZE];
        let mut input = MaybeUninit::<U>::zeroed();

        let input_ptr = input.as_mut_ptr().cast::<u8>();

        
        for i in 0..SIZE {
            let c: u8 = (i % 256) as u8;
            let c = if c == 0 { 42 } else { c };
            let d: u8 = 255_u8 - (i % 256) as u8;
            let d = if d == 0 { 42 } else { d };
            unsafe {
                input_ptr.add(i).write_volatile(c);
                expected[i] = d;
            }
        }

        let c_size = unsafe { ctest_size_of__volatile_char() } as usize;
        if SIZE != c_size {
            FAILED.store(true, Ordering::Relaxed);
            eprintln!(
                "size of `volatile_char` is {c_size} in C and {SIZE} in Rust\n",
            );
            return;
        }

        let mut c_value_bytes = vec![0; size_of::<volatile_char>()];
        let r: U = unsafe {
            ctest_roundtrip__volatile_char(input, is_padding_byte.as_ptr(), c_value_bytes.as_mut_ptr())
        };

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = unsafe { *input_ptr.add(i) };
            let c = c_value_bytes[i];
            if rust != c {
                eprintln!("rust[{}] = {} != {} (C): Rust `volatile_char` -> C", i, rust, c);
                FAILED.store(true, Ordering::Relaxed);
            }
        }

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = expected[i] as usize;
            let c = unsafe { (&raw const r).cast::<u8>().add(i).read_volatile() as usize };
            if rust != c {
                eprintln!(
                    "rust [{i}] = {rust} != {c} (C): C `volatile_char` -> Rust",
                );
                FAILED.store(true, Ordering::Relaxed);
            }
        }
    }

    fn roundtrip_padding__Color() -> Vec<bool> {
        if 0 == 0 {
            
            return vec![!true; size_of::<Color>()]
        }

        
        #[allow(unused_mut)]
        let mut v = Vec::<(usize, usize)>::new();
        #[allow(unused_variables)]
        let bar = MaybeUninit::<Color>::zeroed();
        #[allow(unused_variables)]
        let bar = bar.as_ptr();
        
        let mut is_padding_byte = vec![true; size_of::<Color>()];
        for (off, size) in &v {
            for i in 0..*size {
                is_padding_byte[off + i] = false;
            }
        }
        is_padding_byte
    }

    
    pub fn ctest_roundtrip_Color() {
        type U = Color;
        extern "C" {
            fn ctest_size_of__Color() -> u64;
            fn ctest_roundtrip__Color(
                input: MaybeUninit<U>, is_padding_byte: *const bool, value_bytes: *mut u8
            ) -> U;
        }

        const SIZE: usize = size_of::<U>();

        let is_padding_byte = roundtrip_padding__Color();
        let mut expected = vec![0u8; SIZE];
        let mut input = MaybeUninit::<U>::zeroed();

        let input_ptr = input.as_mut_ptr().cast::<u8>();

        
        for i in 0..SIZE {
            let c: u8 = (i % 256) as u8;
            let c = if c == 0 { 42 } else { c };
            let d: u8 = 255_u8 - (i % 256) as u8;
            let d = if d == 0 { 42 } else { d };
            unsafe {
                input_ptr.add(i).write_volatile(c);
                expected[i] = d;
            }
        }

        let c_size = unsafe { ctest_size_of__Color() } as usize;
        if SIZE != c_size {
            FAILED.store(true, Ordering::Relaxed);
            eprintln!(
                "size of `enum Color` is {c_size} in C and {SIZE} in Rust\n",
            );
            return;
        }

        let mut c_value_bytes = vec![0; size_of::<Color>()];
        let r: U = unsafe {
            ctest_roundtrip__Color(input, is_padding_byte.as_ptr(), c_value_bytes.as_mut_ptr())
        };

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = unsafe { *input_ptr.add(i) };
            let c = c_value_bytes[i];
            if rust != c {
                eprintln!("rust[{}] = {} != {} (C): Rust `Color` -> C", i, rust, c);
                FAILED.store(true, Ordering::Relaxed);
            }
        }

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = expected[i] as usize;
            let c = unsafe { (&raw const r).cast::<u8>().add(i).read_volatile() as usize };
            if rust != c {
                eprintln!(
                    "rust [{i}] = {rust} != {c} (C): C `Color` -> Rust",
                );
                FAILED.store(true, Ordering::Relaxed);
            }
        }
    }

    fn roundtrip_padding__Person() -> Vec<bool> {
        if 4 == 0 {
            
            return vec![!false; size_of::<Person>()]
        }

        
        #[allow(unused_mut)]
        let mut v = Vec::<(usize, usize)>::new();
        #[allow(unused_variables)]
        let bar = MaybeUninit::<Person>::zeroed();
        #[allow(unused_variables)]
        let bar = bar.as_ptr();

        let ty_ptr = unsafe { &raw const ((*bar).name) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Person, name);
        v.push((off, size));

        let ty_ptr = unsafe { &raw const ((*bar).age) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Person, age);
        v.push((off, size));

        let ty_ptr = unsafe { &raw const ((*bar).job) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Person, job);
        v.push((off, size));

        let ty_ptr = unsafe { &raw const ((*bar).favorite_color) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Person, favorite_color);
        v.push((off, size));
        
        let mut is_padding_byte = vec![true; size_of::<Person>()];
        for (off, size) in &v {
            for i in 0..*size {
                is_padding_byte[off + i] = false;
            }
        }
        is_padding_byte
    }

    
    pub fn ctest_roundtrip_Person() {
        type U = Person;
        extern "C" {
            fn ctest_size_of__Person() -> u64;
            fn ctest_roundtrip__Person(
                input: MaybeUninit<U>, is_padding_byte: *const bool, value_bytes: *mut u8
            ) -> U;
        }

        const SIZE: usize = size_of::<U>();

        let is_padding_byte = roundtrip_padding__Person();
        let mut expected = vec![0u8; SIZE];
        let mut input = MaybeUninit::<U>::zeroed();

        let input_ptr = input.as_mut_ptr().cast::<u8>();

        
        for i in 0..SIZE {
            let c: u8 = (i % 256) as u8;
            let c = if c == 0 { 42 } else { c };
            let d: u8 = 255_u8 - (i % 256) as u8;
            let d = if d == 0 { 42 } else { d };
            unsafe {
                input_ptr.add(i).write_volatile(c);
                expected[i] = d;
            }
        }

        let c_size = unsafe { ctest_size_of__Person() } as usize;
        if SIZE != c_size {
            FAILED.store(true, Ordering::Relaxed);
            eprintln!(
                "size of `struct Person` is {c_size} in C and {SIZE} in Rust\n",
            );
            return;
        }

        let mut c_value_bytes = vec![0; size_of::<Person>()];
        let r: U = unsafe {
            ctest_roundtrip__Person(input, is_padding_byte.as_ptr(), c_value_bytes.as_mut_ptr())
        };

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = unsafe { *input_ptr.add(i) };
            let c = c_value_bytes[i];
            if rust != c {
                eprintln!("rust[{}] = {} != {} (C): Rust `Person` -> C", i, rust, c);
                FAILED.store(true, Ordering::Relaxed);
            }
        }

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = expected[i] as usize;
            let c = unsafe { (&raw const r).cast::<u8>().add(i).read_volatile() as usize };
            if rust != c {
                eprintln!(
                    "rust [{i}] = {rust} != {c} (C): C `Person` -> Rust",
                );
                FAILED.store(true, Ordering::Relaxed);
            }
        }
    }

    fn roundtrip_padding__Word() -> Vec<bool> {
        if 2 == 0 {
            
            return vec![!false; size_of::<Word>()]
        }

        
        #[allow(unused_mut)]
        let mut v = Vec::<(usize, usize)>::new();
        #[allow(unused_variables)]
        let bar = MaybeUninit::<Word>::zeroed();
        #[allow(unused_variables)]
        let bar = bar.as_ptr();

        let ty_ptr = unsafe { &raw const ((*bar).word) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Word, word);
        v.push((off, size));

        let ty_ptr = unsafe { &raw const ((*bar).byte) };
        let val = unsafe { ty_ptr.read_unaligned() };

        let size = size_of_val(&val);
        let off = offset_of!(Word, byte);
        v.push((off, size));
        
        let mut is_padding_byte = vec![true; size_of::<Word>()];
        for (off, size) in &v {
            for i in 0..*size {
                is_padding_byte[off + i] = false;
            }
        }
        is_padding_byte
    }

    
    pub fn ctest_roundtrip_Word() {
        type U = Word;
        extern "C" {
            fn ctest_size_of__Word() -> u64;
            fn ctest_roundtrip__Word(
                input: MaybeUninit<U>, is_padding_byte: *const bool, value_bytes: *mut u8
            ) -> U;
        }

        const SIZE: usize = size_of::<U>();

        let is_padding_byte = roundtrip_padding__Word();
        let mut expected = vec![0u8; SIZE];
        let mut input = MaybeUninit::<U>::zeroed();

        let input_ptr = input.as_mut_ptr().cast::<u8>();

        
        for i in 0..SIZE {
            let c: u8 = (i % 256) as u8;
            let c = if c == 0 { 42 } else { c };
            let d: u8 = 255_u8 - (i % 256) as u8;
            let d = if d == 0 { 42 } else { d };
            unsafe {
                input_ptr.add(i).write_volatile(c);
                expected[i] = d;
            }
        }

        let c_size = unsafe { ctest_size_of__Word() } as usize;
        if SIZE != c_size {
            FAILED.store(true, Ordering::Relaxed);
            eprintln!(
                "size of `union Word` is {c_size} in C and {SIZE} in Rust\n",
            );
            return;
        }

        let mut c_value_bytes = vec![0; size_of::<Word>()];
        let r: U = unsafe {
            ctest_roundtrip__Word(input, is_padding_byte.as_ptr(), c_value_bytes.as_mut_ptr())
        };

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = unsafe { *input_ptr.add(i) };
            let c = c_value_bytes[i];
            if rust != c {
                eprintln!("rust[{}] = {} != {} (C): Rust `Word` -> C", i, rust, c);
                FAILED.store(true, Ordering::Relaxed);
            }
        }

        
        for (i, is_padding_byte) in is_padding_byte.iter().enumerate() {
            if *is_padding_byte { continue; }
            let rust = expected[i] as usize;
            let c = unsafe { (&raw const r).cast::<u8>().add(i).read_volatile() as usize };
            if rust != c {
                eprintln!(
                    "rust [{i}] = {rust} != {c} (C): C `Word` -> Rust",
                );
                FAILED.store(true, Ordering::Relaxed);
            }
        }
    }

/* Check if the Rust and C side function pointers point to the same underlying function. */

    pub fn ctest_foreign_fn_calloc() {
        extern "C" {
            fn ctest_foreign_fn__calloc() -> unsafe extern "C" fn();
        }
        let actual = unsafe { ctest_foreign_fn__calloc() } as u64;
        let expected = calloc as *const () as u64;
        check_same(actual, expected, "`calloc` function pointer");
    }

/* Tests if the pointer to the static variable matches in both Rust and C. */

    pub fn ctest_static_byte() {
        extern "C" {
            fn ctest_static__byte() -> *const Byte;
        }
        let actual = (&raw const byte).addr();
        let expected = unsafe {
            ctest_static__byte().addr()
        };
        check_same(actual, expected, "`byte` static");
    }
}

use generated_tests::*;

fn main() {
    println!("RUNNING ALL TESTS");
    run_all();
    if FAILED.load(std::sync::atomic::Ordering::Relaxed) {
        panic!("some tests failed");
    } else {
        println!(
            "PASSED {} tests",
            NTESTS.load(std::sync::atomic::Ordering::Relaxed)
        );
    }
}

// Run all tests by calling the functions that define them.
// FIXME(ctest): Maybe consider running the tests in parallel, since everything is independent
// and we already use atomics.
fn run_all() {
    ctest_const_RED();
    ctest_const_BLUE();
    ctest_const_GREEN();
    ctest_const_cstr_A();
    ctest_const_cstr_B();
    ctest_size_align_Byte();
    ctest_size_align_volatile_char();
    ctest_size_align_gregset_t();
    ctest_size_align_Color();
    ctest_size_align_Person();
    ctest_size_align_Word();
    ctest_signededness_Byte();
    ctest_signededness_volatile_char();
    ctest_field_size_offset_Person_name();
    ctest_field_size_offset_Person_age();
    ctest_field_size_offset_Person_job();
    ctest_field_size_offset_Person_favorite_color();
    ctest_field_size_offset_Word_word();
    ctest_field_size_offset_Word_byte();
    ctest_field_ptr_Person_name();
    ctest_field_ptr_Person_age();
    ctest_field_ptr_Person_job();
    ctest_field_ptr_Person_favorite_color();
    ctest_field_ptr_Word_word();
    ctest_field_ptr_Word_byte();
    ctest_roundtrip_Byte();
    ctest_roundtrip_volatile_char();
    ctest_roundtrip_Color();
    ctest_roundtrip_Person();
    ctest_roundtrip_Word();
    ctest_foreign_fn_calloc();
    ctest_static_byte();
}
