1use libc::{c_char, c_int};
2
3pub type AssertCB = unsafe extern "C" fn(*const c_char, c_int, *const c_char);
4
5#[link(name = "kernaux")]
6extern "C" {
7 #[link_name = "kernaux_assert_do"]
8 pub fn assert_do(file: *const c_char, line: c_int, msg: *const c_char);
9
10 #[link_name = "kernaux_assert_cb"]
11 pub static mut assert_cb: Option<AssertCB>;
12}
13
14#[cfg(test)]
15mod tests {
16 use super::*;
17
18 use std::ffi::{CStr, CString};
19 use std::ptr::null;
20
21 static mut LAST_FILE: *const c_char = null();
22 static mut LAST_LINE: c_int = 0;
23 static mut LAST_MSG: *const c_char = null();
24
25 unsafe extern "C" fn some_assert_cb(
26 file: *const c_char,
27 line: c_int,
28 msg: *const c_char,
29 ) {
30 LAST_FILE = file;
31 LAST_LINE = line;
32 LAST_MSG = msg;
33 }
34
35 #[test]
36 fn default() {
37 unsafe {
38 assert_cb = None;
39 assert!(assert_cb.is_none());
40
41 assert_cb = Some(some_assert_cb);
42 match assert_cb {
43 None => panic!(),
44 Some(actual_assert_cb) => {
45 assert!(actual_assert_cb == some_assert_cb)
46 }
47 }
48
49 let file_cstr = CString::new("foo.rs").unwrap();
50 let msg_cstr = CString::new("bar").unwrap();
51
52 assert_do(
53 file_cstr.as_ptr() as *const c_char,
54 123,
55 msg_cstr.as_ptr() as *const c_char,
56 );
57
58 let file = CStr::from_ptr(LAST_FILE).to_str().unwrap();
59 let line = LAST_LINE;
60 let msg = CStr::from_ptr(LAST_MSG).to_str().unwrap();
61
62 assert_eq!(file, "foo.rs");
63 assert_eq!(line, 123);
64 assert_eq!(msg, "bar");
65 }
66 }
67}