use std::rc::{Rc, Weak}; use std::sync::Arc; use clone_cell::cell::Cell; #[test] fn copy_fields() { struct Foo { x: Cell, y: Cell, } let f = Rc::new(Foo { x: Cell::new(0), y: Cell::new(0), }); f.x.set(42); f.y.set(f.x.get()); assert_eq!(f.x.get(), 42); assert_eq!(f.y.get(), 42); } #[test] fn pure_clone_fields() { struct Foo { x: Cell>, y: Cell>>, } let f = Rc::new(Foo { x: Cell::new(Rc::new(0)), y: Cell::new(None), }); let i = Rc::new(42); f.x.set(i.clone()); f.y.set(Some(i)); assert_eq!(*f.x.get(), 42); assert_eq!(*f.y.get().unwrap(), 42); f.x.set(Rc::new(0)); assert_eq!(*f.x.get(), 0); assert_eq!(*f.y.get().unwrap(), 42); } #[test] fn pure_clone_fields_arc() { struct Foo { x: Cell>, y: Cell>>, } let f = Rc::new(Foo { x: Cell::new(Arc::new(0)), y: Cell::new(None), }); let i = Arc::new(42); f.x.set(i.clone()); f.y.set(Some(i)); assert_eq!(*f.x.get(), 42); assert_eq!(*f.y.get().unwrap(), 42); f.x.set(Arc::new(0)); assert_eq!(*f.x.get(), 0); assert_eq!(*f.y.get().unwrap(), 42); } #[test] fn pure_clone_tuple() { let i = Rc::new(0); let x = Cell::new((i.clone(), Some(Rc::downgrade(&i)))); x.set((Rc::new(42), None)); assert_eq!(*x.get().0, 42); } #[test] fn bad_drop() { struct Foo { ptr: Rc>>, } impl Drop for Foo { fn drop(&mut self) { // Triggers `drop` again... self.ptr.set(None); } } let c = Rc::new(Cell::new(None)); c.set(Some(Foo { ptr: c.clone() })); c.set(None); assert_eq!(c.take().is_none(), true); } #[test] fn cycle() { struct Observer { observable: Cell>, } impl Observer { fn new(observable: Rc) -> Rc { let this = Rc::new(Self { observable: Cell::new(observable), }); this.observable.get().observer.set(Rc::downgrade(&this)); this } fn poke_observable(&self) { self.observable.get().call_observer(); } fn do_something(&self) { self.observable.set(Observable::new()); } } struct Observable { observer: Cell>, } impl Observable { fn new() -> Rc { Rc::new(Self { observer: Cell::new(Weak::new()), }) } fn call_observer(&self) { self.observer.get().upgrade().unwrap().do_something(); } } let observable = Observable::new(); let weak_observable = Rc::downgrade(&observable); let observer = Observer::new(observable); observer.poke_observable(); assert_eq!(weak_observable.upgrade().is_none(), true); }