use std::ops::Deref;
use std::ops::DerefMut;
use crate::Holder;
use crate::Owner;
use crate::OwnerRef;
use crate::State;
use crate::Viewer;
use crate::ViewerRef;
#[test]
fn test_example_owner_viewer_holder() -> Result<(), State> {
let mut owner = Owner::new("hello".to_owned());
owner.push_str(" world!");
assert_eq!(&**owner, "hello world!");
let viewer1 = Viewer::from(owner);
assert_eq!(&**viewer1, "hello world!");
let viewer2 = Viewer::clone(&viewer1);
assert_eq!(&**viewer2, "hello world!");
let holder = Holder::from(viewer1);
let owner = Owner::try_from(viewer2).unwrap();
Owner::drop_data(owner);
Holder::reinit(&holder, "hello new world!".to_owned()).unwrap();
let owner = Owner::try_from(holder).unwrap();
assert_eq!(&**owner, "hello new world!");
Ok(())
}
#[test]
fn test_example_ref() -> Result<(), State> {
let owner = Owner::new(("hello".to_owned(), 1));
let mut owner_ref0 = OwnerRef::from(owner);
owner_ref0.0.push_str(" world");
assert_eq!(owner_ref0.0, "hello world");
owner_ref0.1 = 2;
assert_eq!(owner_ref0.1, 2);
let mut owner_ref1 = OwnerRef::map(owner_ref0, |t| &mut t.0);
owner_ref1.push('!');
assert_eq!(&*owner_ref1, "hello world!");
let owner_ref2 = OwnerRef::map(owner_ref1, |s| &mut s[6 ..]);
assert_eq!(&*owner_ref2, "world!");
let owner = Owner::from(owner_ref2);
let viewer = Viewer::from(owner);
let viewer_ref0 = ViewerRef::from(viewer);
let viewer_ref1 = ViewerRef::map(viewer_ref0, |t| &t.0);
let viewer_ref2 = ViewerRef::map(viewer_ref1, |s| &s[6 ..]);
assert_eq!(&*viewer_ref2, "world!");
Ok(())
}
#[test]
fn test_holder() -> Result<(), State> {
let h1 = Holder::new("".to_owned());
assert_state(Holder::state(&h1), false, 1, 0, false);
let h2 = Holder::clone(&h1);
assert_state(Holder::state(&h1), false, 2, 0, false);
{
let h3 = Holder::clone(&h1);
assert_state(Holder::state(&h1), false, 3, 0, false);
{
let _ = Holder::clone(&h1);
assert_state(Holder::state(&h1), false, 3, 0, false);
}
assert_state(Holder::state(&h1), false, 3, 0, false);
drop(h3);
assert_state(Holder::state(&h1), false, 2, 0, false);
}
assert_state(Holder::state(&h1), false, 2, 0, false);
let h4 = Holder::clone(&h1);
assert_state(Holder::state(&h1), false, 3, 0, false);
let h5 = Holder::clone(&h1);
assert_state(Holder::state(&h1), false, 4, 0, false);
drop(h4);
assert_state(Holder::state(&h1), false, 3, 0, false);
drop(h2);
assert_state(Holder::state(&h1), false, 2, 0, false);
drop(h5);
assert_state(Holder::state(&h1), false, 1, 0, false);
drop(h1);
Ok(())
}
#[test]
fn test_viewer() -> Result<(), State> {
let v1 = Viewer::new("".to_owned());
assert_state(Viewer::state(&v1), false, 0, 1, false);
let v2 = Viewer::clone(&v1);
assert_state(Viewer::state(&v1), false, 0, 2, false);
{
let v3 = Viewer::clone(&v1);
assert_state(Viewer::state(&v1), false, 0, 3, false);
{
let _ = Viewer::clone(&v1);
assert_state(Viewer::state(&v1), false, 0, 3, false);
}
assert_state(Viewer::state(&v1), false, 0, 3, false);
drop(v3);
assert_state(Viewer::state(&v1), false, 0, 2, false);
}
assert_state(Viewer::state(&v1), false, 0, 2, false);
let v4 = Viewer::clone(&v1);
assert_state(Viewer::state(&v1), false, 0, 3, false);
let v5 = Viewer::clone(&v1);
assert_state(Viewer::state(&v1), false, 0, 4, false);
drop(v4);
assert_state(Viewer::state(&v1), false, 0, 3, false);
drop(v2);
assert_state(Viewer::state(&v1), false, 0, 2, false);
drop(v5);
assert_state(Viewer::state(&v1), false, 0, 1, false);
drop(v1);
Ok(())
}
#[test]
fn test_owner() -> Result<(), State> {
let o = Owner::new("".to_owned());
assert!(Owner::state(&o).is_owned());
drop(o);
Ok(())
}
#[test]
fn test_holder_viewer_owner() -> Result<(), State> {
let h1 = Holder::new("".to_owned());
assert_state(Holder::state(&h1), false, 1, 0, false);
let v1 = Viewer::try_from(&h1)?; assert_state(Holder::state(&h1), false, 1, 1, false);
let v2 = Viewer::clone(&v1); assert_state(Holder::state(&h1), false, 1, 2, false);
let _ = Holder::clone(&h1); assert_state(Holder::state(&h1), false, 1, 2, false);
Owner::try_from(&h1).unwrap_err(); assert_state(Holder::state(&h1), false, 1, 2, false);
let _ = Holder::from(&v1); assert_state(Holder::state(&h1), false, 1, 2, false);
drop(v1);
assert_state(Holder::state(&h1), false, 1, 1, false);
Owner::try_from(&h1).unwrap_err(); assert_state(Holder::state(&h1), false, 1, 1, false);
drop(v2);
assert_state(Holder::state(&h1), false, 1, 0, false);
let o1 = Owner::try_from(&h1)?; assert_state(Holder::state(&h1), false, 1, 0, true);
Owner::try_from(&h1).unwrap_err(); assert_state(Holder::state(&h1), false, 1, 0, true);
Viewer::try_from(&h1).unwrap_err(); assert_state(Holder::state(&h1), false, 1, 0, true);
let _ = Holder::clone(&h1); assert_state(Holder::state(&h1), false, 1, 0, true);
drop(o1);
assert_state(Holder::state(&h1), false, 1, 0, false);
let v3 = Viewer::try_from(&h1)?; assert_state(Holder::state(&h1), false, 1, 1, false);
drop(v3);
assert_state(Holder::state(&h1), false, 1, 0, false);
let o2 = Owner::try_from(&h1)?;
assert_state(Holder::state(&h1), false, 1, 0, true);
Owner::drop_data(o2);
assert_state(Holder::state(&h1), true, 1, 0, false);
Viewer::try_from(&h1).unwrap_err();
assert_state(Holder::state(&h1), true, 1, 0, false);
let _ = Holder::clone(&h1);
assert_state(Holder::state(&h1), true, 1, 0, false);
Holder::reinit(&h1, "reinit".to_owned())?;
assert_state(Holder::state(&h1), false, 1, 0, false);
drop(h1);
Ok(())
}
fn assert_state(
state: State, is_dropped: bool, holder_cnt: usize, viewer_cnt: usize, is_owned: bool,
) {
assert_eq!(state.is_dropped(), is_dropped);
assert_eq!(state.holder_count(), holder_cnt);
assert_eq!(state.viewer_count(), viewer_cnt);
assert_eq!(state.is_owned(), is_owned);
}
#[test]
fn test_deref() -> Result<(), State> {
let v1 = Viewer::new("".to_owned());
let v2 = Viewer::clone(&v1);
assert_eq!(v1.deref(), "");
assert_eq!(v2.deref(), "");
Ok(())
}
#[test]
fn test_deref_mut() -> Result<(), State> {
let mut o = Owner::new("".to_owned());
assert_eq!(o.deref(), "");
{
let s = o.deref_mut();
s.push('1');
}
assert_eq!(o.deref(), "1");
Ok(())
}
#[test]
fn test_take() -> Result<(), State> {
let o = Owner::new("123".to_owned());
let h = Holder::from(&o);
let s = Owner::move_data(o);
assert_eq!(s, "123".to_owned());
Viewer::try_from(&h).unwrap_err();
Owner::try_from(&h).unwrap_err();
Ok(())
}
#[test]
fn test_reinit() -> Result<(), State> {
let o = Owner::new("123".to_owned());
let h = Holder::from(&o);
Owner::drop_data(o);
Holder::reinit(&h, "321".to_owned())?;
let v = Viewer::try_from(&h)?;
assert_eq!(v.deref(), "321");
Ok(())
}
#[test]
fn test_circular() -> Result<(), State> {
struct Circular {
_ref: Option<Box<Holder<Circular>>>,
}
let mut o: Owner<Circular> = Owner::new(Circular { _ref: None });
let h = Holder::from(&o);
*o = Circular { _ref: Some(Box::new(h)) };
drop(o);
Ok(())
}