use std::ffi::CString;
use std::ptr;
use drop_struct_macro_derive::DropStructMacro;
use ffi_toolkit::{
catch_panic_response, code_and_message_impl, free_c_str, raw_ptr, CodeAndMessage,
FCPResponseStatus,
};
#[repr(C)]
#[derive(DropStructMacro)]
pub struct BasicResponse {
pub status_code: FCPResponseStatus,
pub error_msg: *const libc::c_char,
pub is_valid: bool,
}
impl Default for BasicResponse {
fn default() -> Self {
BasicResponse {
status_code: FCPResponseStatus::FCPNoError,
error_msg: ptr::null(),
is_valid: false,
}
}
}
code_and_message_impl!(BasicResponse);
unsafe extern "C" fn fn_does_not_panic() -> *mut BasicResponse {
let mut response = BasicResponse::default();
response.is_valid = true;
raw_ptr(response)
}
unsafe extern "C" fn fn_does_not_panic_with_catch_panic() -> *mut BasicResponse {
catch_panic_response(|| {
let mut response = BasicResponse::default();
response.is_valid = true;
raw_ptr(response)
})
}
unsafe extern "C" fn fn_does_panic_with_catch_panic() -> *mut BasicResponse {
catch_panic_response(|| panic!("I do panic"))
}
#[test]
fn does_not_panic() {
unsafe {
let response = fn_does_not_panic();
assert!((*response).is_valid);
assert_eq!((*response).status_code, FCPResponseStatus::FCPNoError);
assert_eq!((*response).error_msg, ptr::null());
}
}
#[test]
fn does_not_panic_with_catch_panic_response() {
unsafe {
let response = fn_does_not_panic_with_catch_panic();
assert!((*response).is_valid);
assert_eq!((*response).status_code, FCPResponseStatus::FCPNoError);
assert_eq!((*response).error_msg, ptr::null());
}
}
#[test]
fn does_panic_with_catch_panic_response() {
unsafe {
let response = fn_does_panic_with_catch_panic();
assert!(!(*response).is_valid);
assert_eq!(
(*response).status_code,
FCPResponseStatus::FCPUnclassifiedError
);
let error_message = CString::from_raw((*response).error_msg as *mut _)
.into_string()
.unwrap();
assert_eq!(error_message, "Rust panic: I do panic");
}
}