use core::{marker::PhantomPinned, pin::Pin, sync::atomic::Ordering::Relaxed};
use std::sync::{Arc, Weak, atomic::AtomicUsize};
use crate::{Atomic, AtomicOption, PotentialAtomicOption, PotentialWell};
#[test]
fn drop_empty() {
let atomic = <AtomicOption<Box<&str>>>::none();
drop(atomic);
}
#[test]
fn drop_emptied() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
atomic.take(Relaxed).unwrap();
drop(atomic);
}
#[test]
fn drop_filled() {
let atomic = <AtomicOption<Box<&str>>>::none();
assert_eq!(
atomic.insert(Box::new("hello world"), Relaxed, Relaxed),
Ok(())
);
drop(atomic);
}
#[test]
fn drop_nonempty() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
drop(atomic);
}
#[test]
fn drop_nonoptional() {
let atomic = <Atomic<Box<&str>>>::new(Box::new("hello world"));
drop(atomic);
}
#[test]
fn drop_nonoptional_swapped() {
let atomic = <Atomic<Box<&str>>>::new(Box::new("hello world"));
atomic.swap(Box::new("hallo whirl"), Relaxed);
drop(atomic);
}
#[test]
fn drop_swapped() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
atomic.swap(Box::new("hallo whirl"), Relaxed);
drop(atomic);
}
#[test]
fn insert_failure() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
assert_eq!(
atomic.insert(Box::new("hallo whirl"), Relaxed, Relaxed),
Err(Box::new("hallo whirl"))
);
drop(atomic);
}
#[test]
fn load_empty() {
let atomic = <AtomicOption<Box<&str>>>::none();
assert_eq!(atomic.load(Relaxed), None);
drop(atomic);
}
#[test]
fn load_nonempty() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
assert_eq!(atomic.load(Relaxed), Some(&"hello world"));
drop(atomic);
}
#[test]
fn load_empty_mut() {
let mut atomic = <AtomicOption<Box<&str>>>::none();
assert_eq!(atomic.load_mut(), None);
drop(atomic);
}
#[test]
fn load_nonempty_mut() {
let mut atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
*atomic.load_mut().unwrap() = "good bye, world!";
assert_eq!(atomic.load(Relaxed), Some(&"good bye, world!"));
drop(atomic);
}
#[test]
fn load() {
let atomic = <Atomic<Box<&str>>>::new(Box::new("hello world"));
assert_eq!(atomic.load(Relaxed), &"hello world");
drop(atomic);
}
#[test]
fn load_mut() {
let mut atomic = <Atomic<Box<&str>>>::new(Box::new("hello world"));
*atomic.load_mut() = "good bye, world!";
assert_eq!(atomic.load(Relaxed), &"good bye, world!");
drop(atomic);
}
#[test]
fn take_failure() {
let atomic = <AtomicOption<Box<&str>>>::none();
assert_eq!(atomic.take(Relaxed), None);
drop(atomic);
}
#[test]
fn clone_empty() {
let atomic = <AtomicOption<Box<&str>>>::none();
assert_eq!(atomic.load_clone(Relaxed), None);
drop(atomic);
}
#[test]
fn clone_nonempty() {
let atomic = <AtomicOption<Box<&str>>>::some(Box::new("hello world"));
assert_eq!(atomic.load_clone(Relaxed), Some(Box::new("hello world")));
drop(atomic);
}
#[test]
fn clone() {
let atomic = <Atomic<Box<&str>>>::new(Box::new("hello world"));
assert_eq!(atomic.load_clone(Relaxed), Box::new("hello world"));
drop(atomic);
}
struct Pinned {
marker: PhantomPinned,
data: &'static str,
}
impl Pinned {
fn new(data: &'static str) -> Pinned {
Pinned {
marker: PhantomPinned,
data,
}
}
}
#[test]
fn pinned() {
let mut atomic = <Atomic<Pin<Box<Pinned>>>>::new(Box::pin(Pinned::new("hello, world!")));
assert_eq!(
atomic.load_mut_pinned().into_ref().get_ref().data,
"hello, world!"
);
drop(atomic);
}
#[test]
fn pinned_empty() {
let mut atomic = <AtomicOption<Pin<Box<Pinned>>>>::none();
assert!(atomic.load_mut_pinned().is_none());
drop(atomic);
}
#[test]
fn pinned_nonempty() {
let mut atomic = <AtomicOption<Pin<Box<Pinned>>>>::some(Box::pin(Pinned::new("hello, world!")));
assert_eq!(
atomic.load_mut_pinned().unwrap().into_ref().get_ref().data,
"hello, world!"
);
drop(atomic);
}
#[allow(unused)]
struct BasicLink<T, W: PotentialWell> {
data: T,
next: PotentialAtomicOption<BasicLink<T, W>, W>,
}
#[allow(unused)]
struct AdvancedLink<T> {
data: T,
next: PotentialAtomicOption<AdvancedLink<T>, Arc<()>>,
prev: PotentialAtomicOption<AdvancedLink<T>, Weak<()>>,
}
struct DropCheck<'a> {
idx: usize,
check: &'a AtomicUsize,
}
impl Drop for DropCheck<'_> {
fn drop(&mut self) {
assert_eq!(self.check.fetch_add(1, Relaxed), self.idx);
}
}
#[test]
fn basic_linked_list() {
let check = AtomicUsize::new(0);
let list: BasicLink<DropCheck<'_>, Box<()>> = BasicLink {
data: DropCheck {
idx: 0,
check: &check,
},
next: PotentialAtomicOption::some(Box::new(BasicLink {
data: DropCheck {
idx: 1,
check: &check,
},
next: PotentialAtomicOption::some(Box::new(BasicLink {
data: DropCheck {
idx: 2,
check: &check,
},
next: PotentialAtomicOption::none(),
})),
})),
};
drop(list);
}
#[test]
fn advanced_linked_list() {
let check = AtomicUsize::new(0);
let first = Arc::new(AdvancedLink {
data: DropCheck {
idx: 0,
check: &check,
},
next: PotentialAtomicOption::none(),
prev: PotentialAtomicOption::none(),
});
let middle = Arc::new(AdvancedLink {
data: DropCheck {
idx: 1,
check: &check,
},
next: PotentialAtomicOption::none(),
prev: PotentialAtomicOption::none(),
});
let last = Arc::new(AdvancedLink {
data: DropCheck {
idx: 2,
check: &check,
},
next: PotentialAtomicOption::none(),
prev: PotentialAtomicOption::none(),
});
let Ok(()) = last.prev.insert(Arc::downgrade(&middle), Relaxed, Relaxed) else {
unreachable!()
};
let Ok(()) = middle.prev.insert(Arc::downgrade(&first), Relaxed, Relaxed) else {
unreachable!()
};
let Ok(()) = middle.next.insert(last, Relaxed, Relaxed) else {
unreachable!()
};
let Ok(()) = first.next.insert(middle, Relaxed, Relaxed) else {
unreachable!()
};
let list: Arc<AdvancedLink<DropCheck<'_>>> = first;
drop(list);
}