use crate::{Atom, Atomic, Ordering};
macro_rules! generic_tests {
($ty:ty, $val0:expr, $val1:expr) => {
#[test]
fn new() {
let _: Atomic<$ty> = Atomic::new($val0);
}
#[test]
fn load_store() {
let a = Atomic::new($val0);
assert_eq!(a.load(Ordering::SeqCst), $val0);
a.store($val1, Ordering::SeqCst);
assert_eq!(a.load(Ordering::SeqCst), $val1);
}
#[test]
fn into_inner() {
let a = Atomic::new($val0);
assert_eq!(a.into_inner(), $val0);
}
#[test]
fn swap() {
let a = Atomic::new($val0);
assert_eq!(a.swap($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val1);
}
#[test]
fn fmt_debug() {
let a = Atomic::new($val0);
assert_eq!(format!("{:?}", a), format!("{:?}", $val0));
}
#[test]
fn from() {
let a = Atomic::new($val0);
let b: Atomic<$ty> = $val0.into();
assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst));
}
};
}
macro_rules! default_tests {
($ty:ty) => {
#[test]
fn default() {
let a: Atomic<$ty> = Default::default();
assert_eq!(a.load(Ordering::SeqCst), <$ty>::default());
}
};
}
macro_rules! serde_tests {
($ty:ty, $val0:expr) => {
#[cfg(feature = "serde")]
use bincode;
#[cfg(feature = "serde")]
#[test]
fn test_serde_round_trip() {
let src = Atomic::new($val0);
let serialized = bincode::serialize(&src).unwrap();
let deserialized: Atomic<$ty> = bincode::deserialize(&serialized).unwrap();
assert_eq!(src.load(Ordering::SeqCst), deserialized.load(Ordering::SeqCst));
}
};
}
macro_rules! logic_tests {
($val0:expr, $val1:expr) => {
#[test]
fn logic() {
let a = Atomic::new($val0);
assert_eq!(a.fetch_and($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val0 & $val1);
let a = Atomic::new($val0);
assert_eq!(a.fetch_nand($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), !($val0 & $val1));
let a = Atomic::new($val0);
assert_eq!(a.fetch_or($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val0 | $val1);
let a = Atomic::new($val0);
assert_eq!(a.fetch_xor($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val0 ^ $val1);
}
};
}
macro_rules! int_tests {
($val0:expr, $val1:expr) => {
#[test]
fn integer() {
let a = Atomic::new($val0);
assert_eq!(a.fetch_add($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val0.wrapping_add($val1));
let a = Atomic::new($val0);
assert_eq!(a.fetch_sub($val1, Ordering::SeqCst), $val0);
assert_eq!(a.load(Ordering::SeqCst), $val0.wrapping_sub($val1));
}
};
}
macro_rules! emit_if {
(n, { $($t:tt)* }) => {};
(y, { $($t:tt)* }) => { $($t)* };
}
macro_rules! gen_tests_for_primitives {
(
$mod_name:ident, $ty:ty, $val0:expr, $val1:expr,
[$with_logic:ident $with_int:ident]
) => {
mod $mod_name {
use super::*;
generic_tests!($ty, $val0, $val1);
default_tests!($ty);
serde_tests!($ty, $val0);
emit_if!($with_logic, { logic_tests!($val0, $val1); });
emit_if!($with_int, { int_tests!($val0, $val1); });
}
};
}
gen_tests_for_primitives!(_bool, bool, true, false, [y n]);
gen_tests_for_primitives!(_u8, u8, 7u8, 33u8, [y y]);
gen_tests_for_primitives!(_i8, i8, 7i8, 33i8, [y y]);
gen_tests_for_primitives!(_u16, u16, 7u16, 33u16, [y y]);
gen_tests_for_primitives!(_i16, i16, 7i16, 33i16, [y y]);
gen_tests_for_primitives!(_u32, u32, 7u32, 33u32, [y y]);
gen_tests_for_primitives!(_i32, i32, 7i32, 33i32, [y y]);
gen_tests_for_primitives!(_u64, u64, 7u64, 33u64, [y y]);
gen_tests_for_primitives!(_i64, i64, 7i64, 33i64, [y y]);
gen_tests_for_primitives!(_usize, usize, 7usize, 33usize, [y y]);
gen_tests_for_primitives!(_isize, isize, 7isize, 33isize, [y y]);
gen_tests_for_primitives!(_f32, f32, 7.0f32, 33.0f32, [n n]);
gen_tests_for_primitives!(_f64, f64, 7.0f64, 33.0f64, [n n]);
gen_tests_for_primitives!(_char, char, 'x', '♥', [n n]);
gen_tests_for_primitives!(_u8array2, [u8; 2], [3u8, 79], [17u8, 240], [n n]);
gen_tests_for_primitives!(_u8array4, [u8; 4], [3u8, 79, 13, 230], [17u8, 240, 59, 184], [n n]);
gen_tests_for_primitives!(_u8array8, [u8; 8], [3u8, 79, 13, 230, 4, 80, 14, 231],
[17u8, 240, 59, 184, 18, 241, 60, 185], [n n]);
gen_tests_for_primitives!(_u16array2, [u16; 2], [3u16, 257], [17u16, 9999], [n n]);
gen_tests_for_primitives!(_u16array4, [u16; 4], [3u16, 257, 13, 230],
[17u16, 9999, 59, 17003], [n n]);
gen_tests_for_primitives!(_u32array2, [u32; 2], [3u32, 77977], [17u32, 190247], [n n]);
gen_tests_for_primitives!(_i8array2, [i8; 2], [3i8, -79], [-17i8, 113], [n n]);
gen_tests_for_primitives!(_i8array4, [i8; 4], [3i8, -79, 13, -120],
[-17i8, 113, -59, -98], [n n]);
gen_tests_for_primitives!(_i8array8, [i8; 8], [3i8, -79, 13, -120, 4, 80, -14, 111],
[-17i8, 113, -59, -98, -18, 114, 60, -128], [n n]);
gen_tests_for_primitives!(_i16array2, [i16; 2], [3i16, -257], [17i16, -9999], [n n]);
gen_tests_for_primitives!(_i16array4, [i16; 4], [3i16, -257, 13, 230],
[17i16, -9999, -59, 17003], [n n]);
gen_tests_for_primitives!(_i32array2, [i32; 2], [3i32, -77977], [-17i32, 190247], [n n]);
mod _ptr {
use super::*;
generic_tests!(Foo, Foo::Nothing, Foo::Set(0b101));
}
mod custom {
use super::*;
generic_tests!(Foo, Foo::Nothing, Foo::Set(0b101));
default_tests!(Foo);
}
#[derive(Debug, PartialEq, Eq)]
enum Foo {
Nothing,
Set(u8),
}
impl Default for Foo {
fn default() -> Self {
Foo::Set(0b10101010)
}
}
impl Atom for Foo {
type Repr = u16;
fn pack(self) -> Self::Repr {
match self {
Foo::Nothing => 0x01FF,
Foo::Set(s) => s as u16,
}
}
fn unpack(src: Self::Repr) -> Self {
if src & 0x0100 != 0 {
Foo::Nothing
} else {
Foo::Set((src & 0xFF) as u8)
}
}
}
macro_rules! gen_tests_for_opt_non_zeroes {
($mod_name:ident, $ty:ident) => {
mod $mod_name {
use super::*;
use std::num::$ty;
generic_tests!(Option<$ty>, $ty::new(7), $ty::new(33));
default_tests!(Option<$ty>);
serde_tests!(Option<$ty>, $ty::new(7));
#[test]
fn integer() {
let a = Atomic::new($ty::new(7));
assert_eq!(a.fetch_add($ty::new(33), Ordering::SeqCst), $ty::new(7));
assert_eq!(a.load(Ordering::SeqCst), $ty::new(40));
let a = Atomic::new($ty::new(33));
assert_eq!(a.fetch_sub($ty::new(7), Ordering::SeqCst), $ty::new(33));
assert_eq!(a.load(Ordering::SeqCst), $ty::new(26));
let a = Atomic::new($ty::new(33));
assert_eq!(a.fetch_sub(None, Ordering::SeqCst), $ty::new(33));
assert_eq!(a.load(Ordering::SeqCst), $ty::new(33));
let a = Atomic::new($ty::new(27));
assert_eq!(a.fetch_sub($ty::new(27), Ordering::SeqCst), $ty::new(27));
assert_eq!(a.load(Ordering::SeqCst), None);
}
}
};
}
gen_tests_for_opt_non_zeroes!(nz_u8, NonZeroU8);
gen_tests_for_opt_non_zeroes!(nz_i8, NonZeroI8);
gen_tests_for_opt_non_zeroes!(nz_u16, NonZeroU16);
gen_tests_for_opt_non_zeroes!(nz_i16, NonZeroI16);
gen_tests_for_opt_non_zeroes!(nz_u32, NonZeroU32);
gen_tests_for_opt_non_zeroes!(nz_i32, NonZeroI32);
gen_tests_for_opt_non_zeroes!(nz_u64, NonZeroU64);
gen_tests_for_opt_non_zeroes!(nz_i64, NonZeroI64);
gen_tests_for_opt_non_zeroes!(nz_usize, NonZeroUsize);
gen_tests_for_opt_non_zeroes!(nz_isize, NonZeroIsize);
fn _atomic_is_always_send_sync<T: Atom>(a: Atomic<T>) {
fn requires_send_sync<X: Send + Sync>(_: X) {}
requires_send_sync(a);
}