use crate::{Own, pin};
use std::sync::{
Arc,
atomic::{AtomicBool, Ordering::Relaxed},
};
#[test]
fn live_ref_get_some() {
let o = Own::new_box(42);
let r = o.refer();
let g = pin();
assert_eq!(r.get(&g), Some(&42));
}
#[test]
fn dead_ref_get_none() {
let o = Own::new_box(42);
let r = o.refer();
drop(o);
let g = pin();
assert_eq!(r.get(&g), None);
}
#[test]
fn dead_ref_get_some_with_pin() {
let o = Own::new_box(42);
let r = o.refer();
let g = pin();
let value = r.get(&g);
drop(o);
assert_eq!(value, Some(&42));
}
#[test]
fn dead_ref_get_none_after_reuse() {
let o = Own::new_box(42);
let r = o.refer();
let o = Own::new_from(Box::new(43), o);
let g = pin();
assert_eq!(r.get(&g), None);
let _ = o;
}
#[test]
fn ref_with_helper() {
let o = Own::new_box(42);
let r = o.refer();
let result = r.inspect(|x| *x * 2);
assert_eq!(result, Some(84));
drop(o);
let result = r.inspect(|x| *x * 2);
assert_eq!(result, None);
}
#[test]
fn ref_map_helper() {
let o = Own::new_box(String::from("hello"));
let r = o.refer();
let mapped = r.map(|s| s.as_str());
let g = pin();
assert_eq!(mapped.get(&g), Some("hello"));
drop(o);
assert_eq!(mapped.get(&g), None);
}
#[test]
fn ref_map_with_guard() {
let o = Own::new_box(vec![1, 2, 3]);
let r = o.refer();
let g = pin();
let mapped = r.map_with(|v| &v[1], &g);
assert_eq!(mapped.get(&g), Some(&2));
drop(o);
assert_eq!(mapped.get(&g), None);
}
#[test]
fn ref_copy_and_clone() {
let o = Own::new_box(42);
let r1 = o.refer();
let r2 = r1;
#[allow(clippy::clone_on_copy)]
let r3 = r1.clone();
let g = pin();
assert_eq!(r1.get(&g), Some(&42));
assert_eq!(r2.get(&g), Some(&42));
assert_eq!(r3.get(&g), Some(&42));
drop(o);
assert_eq!(r1.get(&g), None);
assert_eq!(r2.get(&g), None);
assert_eq!(r3.get(&g), None);
}
#[test]
fn multiple_refs_same_object() {
let o = Own::new_box(42);
let r1 = o.refer();
let r2 = o.refer();
let g = pin();
assert_eq!(r1.get(&g), Some(&42));
assert_eq!(r2.get(&g), Some(&42));
drop(o);
assert_eq!(r1.get(&g), None);
assert_eq!(r2.get(&g), None);
}
#[test]
fn arc_pointer_type() {
let o = Own::new(Arc::new(42));
let r = o.refer();
let g = pin();
assert_eq!(r.get(&g), Some(&42));
drop(o);
assert_eq!(r.get(&g), None);
}
#[test]
fn string_pointer_type() {
let o = Own::new(String::from("hello"));
let r = o.refer();
let g = pin();
assert_eq!(r.get(&g), Some("hello"));
drop(o);
assert_eq!(r.get(&g), None);
}
#[test]
fn vec_pointer_type() {
let o = Own::new(vec![1, 2, 3]);
let r = o.refer();
let g = pin();
assert_eq!(r.get(&g), Some(&[1, 2, 3][..]));
drop(o);
assert_eq!(r.get(&g), None);
}
#[test]
fn unit_pointer_type() {
let o = Own::new(());
let r = o.refer();
let g = pin();
assert_eq!(r.get(&g), Some(&()));
drop(o);
assert_eq!(r.get(&g), None);
}
#[test]
fn sequential_reuse() {
let o1 = Own::new_box(1);
let r1 = o1.refer();
let o2 = Own::new_from(Box::new(2), o1);
let r2 = o2.refer();
let o3 = Own::new_from(Box::new(3), o2);
let g = pin();
assert_eq!(r1.get(&g), None);
assert_eq!(r2.get(&g), None);
assert_eq!(o3.refer().get(&g), Some(&3));
drop(o3);
assert_eq!(r1.get(&g), None);
assert_eq!(r2.get(&g), None);
}
#[test]
fn debug_formatting() {
let o = Own::new_box(42);
let r = o.refer();
let debug_str = format!("{o:?}");
assert!(debug_str.contains("Own"));
assert!(debug_str.contains("42"));
let debug_str = format!("{r:?}");
assert!(debug_str.contains("Ref::Live"));
assert!(debug_str.contains("42"));
drop(o);
let debug_str = format!("{r:?}");
assert!(debug_str.contains("Ref::Dead"));
}
#[test]
fn deref_trait() {
let o = Own::new_box(42);
assert_eq!(*o, 42);
let s = Own::new(String::from("hello"));
assert_eq!(&*s, "hello");
}
#[test]
fn should_drop_on_unpin() {
static HAS_DROPPED: AtomicBool = AtomicBool::new(false);
struct FlagDrop;
impl Drop for FlagDrop {
fn drop(&mut self) {
HAS_DROPPED.store(true, Relaxed);
}
}
for i in 0..10 {
let o = Own::new_box(FlagDrop);
let r = o.refer();
let g = pin();
assert!(r.get(&g).is_some());
drop(o);
assert!(r.get(&g).is_none());
if i == 0 {
assert!(!HAS_DROPPED.load(Relaxed));
}
g.flush();
}
assert!(HAS_DROPPED.load(Relaxed));
}