/* 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)]
    #![deny(improper_ctypes_definitions)]
    use std::ffi::CStr;
    use std::fmt::{Debug, LowerHex};
    use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
    use std::{mem, ptr, slice};

    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);
        }
    }

    /// 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. This
    /// method is the same as `check_same` but prints errors in bytes in hex.
    fn check_same_hex<T: PartialEq + LowerHex + Debug>(rust: T, c: T, attr: &str) {
        if rust != c {
            eprintln!("bad {attr}: rust: {rust:?} ({rust:#x}) != c {c:?} ({c:#x})");
            FAILED.store(true, Ordering::Relaxed);
        } else {
            NTESTS.fetch_add(1, Ordering::Relaxed);
        }
    }
    // Test that the string constant is the same in both Rust and C.
    // While fat pointers can't be translated, we instead of * const c_char.
    pub fn const_A() {
        extern "C" {
            fn __test_const_A() -> *const *const u8;
        }
        let val = A;
        unsafe {
            let ptr = *__test_const_A();
            let val = CStr::from_ptr(ptr.cast::<c_char>());
            let val = val.to_str().expect("const A not utf8");
            let c = ::std::ffi::CStr::from_ptr(ptr as *const _);
            let c = c.to_str().expect("const A not utf8");
            check_same(val, c, "A string");
        }
    }
}

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.
fn run_all() {
    const_A();
}
