use SafeManuallyDrop::ManuallyDrop;
#[inline]
fn build_new_test_vec() -> Vec<String> {
let mut vec = Vec::with_capacity(3);
vec.push("test".into());
vec.push("test2".into());
vec.push("test3".into());
vec
}
#[cfg(feature = "support_panic_trig")]
#[allow(unused_unsafe)]
mod panic_test_methods {
use SafeManuallyDrop::AlwaysSafePanicManuallyDrop as PanicManuallyDrop;
use core::ops::Deref;
use super::build_new_test_vec;
#[inline(never)]
pub (crate) fn test_combo_drop(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data); let _e = control_drop.deref();
{
unsafe {
PanicManuallyDrop::drop(&mut control_drop);
assert_eq!(control_drop.is_next_trig(), true); PanicManuallyDrop::drop(&mut control_drop); }
}
}
#[inline(never)]
pub (crate) fn test_drop_and_read(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data); let _e = control_drop.deref(); let _e = control_drop.deref(); {
unsafe {
PanicManuallyDrop::drop(&mut control_drop); }
}
assert_eq!(control_drop.is_next_trig(), true); let _e = control_drop.deref(); }
#[inline(never)]
pub (crate) fn test_take_and_read(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
let _e = control_drop.deref(); let _e = control_drop.deref(); {
let data = unsafe {
PanicManuallyDrop::take(&mut control_drop) };
assert_eq!(data, build_new_test_vec()); drop(data); }
assert_eq!(control_drop.is_next_trig(), true);
let _e = control_drop.deref(); }
#[inline(never)]
pub (crate) fn test_take_and_drop(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
let _e = control_drop.deref(); let _e = control_drop.deref(); {
let data = unsafe {
PanicManuallyDrop::take(&mut control_drop) };
assert_eq!(data, build_new_test_vec()); drop(data); }
assert_eq!(control_drop.is_next_trig(), true);
unsafe {
PanicManuallyDrop::drop(&mut control_drop); }
}
#[inline(never)]
pub (crate) fn test_drop_and_into_inner(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
let _e = control_drop.deref(); let _e = control_drop.deref(); {
unsafe {
PanicManuallyDrop::drop(&mut control_drop) }
}
assert_eq!(control_drop.is_next_trig(), true);
let _data = PanicManuallyDrop::into_inner(control_drop); }
#[inline(never)]
pub (crate) fn test_expmanualdrop(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
unsafe {
PanicManuallyDrop::drop(&mut control_drop); }
assert_eq!(control_drop.is_next_trig(), true);
let _e = control_drop.deref(); }
#[inline(never)]
pub (crate) fn test_expmanualdrop2_ignorepanic(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
unsafe {
PanicManuallyDrop::drop(&mut control_drop); }
assert_eq!(control_drop.is_next_trig(), true); }
#[inline(never)]
pub (crate) fn test_expmanualdrop3_ignorepanic(data: Vec<String>) {
let mut control_drop = PanicManuallyDrop::new(data);
let data = unsafe {
PanicManuallyDrop::take(&mut control_drop) };
assert_eq!(control_drop.is_next_trig(), true);
drop(control_drop); drop(data); }
}
#[cfg(all(test, feature = "support_panic_trig"))]
#[test]
fn test_panic_mode() {
static mut PANIC_COUNTER: usize = 0;
std::panic::set_hook(Box::new(|panic_info| {
unsafe {
PANIC_COUNTER += 1;
}
println!(
"#[test_trigger, num: {}] {:?}, OK.",
unsafe { PANIC_COUNTER },
panic_info
);
}));
let arr_fn: &[(bool, fn(a: Vec<String>))] = &[
(true, panic_test_methods::test_combo_drop as _),
(true, panic_test_methods::test_drop_and_read as _),
(true, panic_test_methods::test_take_and_read as _),
(true, panic_test_methods::test_take_and_drop as _),
(true, panic_test_methods::test_drop_and_into_inner as _),
(true, panic_test_methods::test_expmanualdrop as _),
(false, panic_test_methods::test_expmanualdrop2_ignorepanic as _),
(false, panic_test_methods::test_expmanualdrop3_ignorepanic as _),
];
let mut c_ignore_panic = 0;
for (is_err, ..) in arr_fn.iter() {
if !is_err {
c_ignore_panic = c_ignore_panic + 1;
}
}
for (is_err, function) in arr_fn.iter() {
let e = std::thread::spawn(|| {
let function = function.clone();
let new_data = build_new_test_vec();
(function)(new_data);
}).join();
assert_eq!(&e.is_err(), is_err);
}
std::panic::set_hook(Box::new(|_| {}));
assert_eq!(unsafe { PANIC_COUNTER }, arr_fn.len() - c_ignore_panic);
}
#[test]
fn test_thread_drop() {
let a = ManuallyDrop::new(vec![1]);
let is_ok = std::thread::spawn(move || {
let mut a = a;
#[allow(unused_unsafe)]
unsafe {
ManuallyDrop::drop(&mut a);
}
true
}).join();
assert_eq!(is_ok.is_ok(), true);
let ok = is_ok.unwrap();
assert_eq!(ok, true);
}