use std::ptr;
use std::sync::Arc;
use get_mut_drop_weak::sync::get_mut_drop_weak;
#[test]
fn test_exclusive_access_no_weak() {
let mut arc = Arc::new(10);
let original_ptr = Arc::as_ptr(&arc);
let result = get_mut_drop_weak(&mut arc);
let val_mut = result.unwrap(); assert_eq!(*val_mut, 10);
*val_mut = 20;
assert_eq!(*arc, 20);
assert_eq!(Arc::strong_count(&arc), 1);
assert_eq!(Arc::weak_count(&arc), 0);
assert_eq!(Arc::as_ptr(&arc), original_ptr);
}
#[test]
fn test_strong_shared_no_mut() {
let mut arc1 = Arc::new(String::from("hello"));
let arc2 = Arc::clone(&arc1);
let original_ptr = Arc::as_ptr(&arc1);
assert_eq!(Arc::strong_count(&arc1), 2);
let result = get_mut_drop_weak(&mut arc1);
let err_ref = result.unwrap_err(); assert!(ptr::eq(err_ref, &arc1));
assert_eq!(*arc1, "hello");
assert_eq!(*arc2, "hello");
assert_eq!(Arc::strong_count(&arc1), 2);
assert_eq!(Arc::weak_count(&arc1), 0);
assert_eq!(Arc::as_ptr(&arc1), original_ptr);
drop(arc2);
assert_eq!(Arc::strong_count(&arc1), 1);
}
#[test]
fn test_strong_shared_with_weak_no_mut() {
let mut arc1 = Arc::new(vec![1, 2, 3]);
let arc2 = Arc::clone(&arc1);
let weak1 = Arc::downgrade(&arc1);
let original_ptr = Arc::as_ptr(&arc1);
assert_eq!(Arc::strong_count(&arc1), 2);
assert_eq!(Arc::weak_count(&arc1), 1);
assert!(weak1.upgrade().is_some());
let result = get_mut_drop_weak(&mut arc1);
let err_ref = result.unwrap_err(); assert!(ptr::eq(err_ref, &arc1));
assert_eq!(*arc1, vec![1, 2, 3]);
assert_eq!(*arc2, vec![1, 2, 3]);
assert_eq!(Arc::strong_count(&arc1), 2);
assert_eq!(Arc::weak_count(&arc1), 1);
assert!(weak1.upgrade().is_some()); assert_eq!(Arc::as_ptr(&arc1), original_ptr);
drop(arc2);
assert_eq!(Arc::strong_count(&arc1), 1);
assert_eq!(Arc::weak_count(&arc1), 1); }
#[test]
fn test_weak_shared_drops_weak_success() {
#[derive(Debug, PartialEq)]
struct TestData {
value: i32,
}
let mut arc = Arc::new(TestData { value: 50 });
let weak1 = Arc::downgrade(&arc);
let weak2 = Arc::downgrade(&arc);
let original_ptr = Arc::as_ptr(&arc);
assert_eq!(Arc::strong_count(&arc), 1);
assert_eq!(Arc::weak_count(&arc), 2);
assert!(weak1.upgrade().is_some());
assert!(weak2.upgrade().is_some());
let result = get_mut_drop_weak(&mut arc);
let val_mut = result.unwrap(); assert_eq!(val_mut.value, 50);
val_mut.value = 60;
assert_eq!(arc.value, 60);
assert_eq!(Arc::strong_count(&arc), 1);
assert_eq!(Arc::weak_count(&arc), 0);
let new_ptr = Arc::as_ptr(&arc);
assert_ne!(new_ptr, original_ptr);
assert!(weak1.upgrade().is_none());
assert!(weak2.upgrade().is_none());
}
#[derive(Debug)]
struct DropTracker<'a> {
id: i32,
dropped: &'a std::sync::atomic::AtomicBool,
}
impl<'a> Drop for DropTracker<'a> {
fn drop(&mut self) {
println!("Dropping DropTracker id: {}", self.id);
self.dropped
.store(true, std::sync::atomic::Ordering::SeqCst);
}
}
#[test]
fn test_weak_shared_drops_weak_with_drop_impl() {
let dropped_flag = std::sync::atomic::AtomicBool::new(false);
let data = DropTracker {
id: 1,
dropped: &dropped_flag,
};
let mut arc = Arc::new(data);
let weak = Arc::downgrade(&arc);
let original_ptr = Arc::as_ptr(&arc);
assert_eq!(Arc::strong_count(&arc), 1);
assert_eq!(Arc::weak_count(&arc), 1);
assert!(!dropped_flag.load(std::sync::atomic::Ordering::SeqCst));
let result = get_mut_drop_weak(&mut arc);
let val_mut = result.unwrap();
val_mut.id = 2;
assert_eq!(val_mut.id, 2);
assert_eq!(Arc::strong_count(&arc), 1);
assert_eq!(Arc::weak_count(&arc), 0); assert_ne!(Arc::as_ptr(&arc), original_ptr); assert!(weak.upgrade().is_none()); assert!(!dropped_flag.load(std::sync::atomic::Ordering::SeqCst));
drop(arc);
assert!(dropped_flag.load(std::sync::atomic::Ordering::SeqCst)); }
#[test]
fn simple_multithreaded() {
use std::{
sync::{Arc, Barrier},
thread,
};
const NUM_WEAK_JOBS: usize = 2;
let arc = Arc::new(Box::new(42usize));
let barrier = Barrier::new(NUM_WEAK_JOBS + 1);
thread::scope(|s| {
for _ in 0..NUM_WEAK_JOBS {
let arc = arc.clone();
s.spawn(|| {
let weak = Arc::downgrade(&arc);
assert!(weak.upgrade().is_some());
barrier.wait(); barrier.wait(); drop(arc);
barrier.wait(); barrier.wait(); assert!(weak.upgrade().is_none());
});
}
let mut arc = arc;
let barrier = &barrier;
s.spawn(move || {
barrier.wait(); get_mut_drop_weak(&mut arc).unwrap_err();
barrier.wait(); barrier.wait(); let b = get_mut_drop_weak(&mut arc).unwrap();
**b += 1;
assert_eq!(**arc, 43);
barrier.wait(); })
.join()
.unwrap();
});
}