// Copyright 2015 Colin Sherratt // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. extern crate atom; use std::thread; use std::sync::*; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use atom::*; #[test] fn swap() { let a = Atom::empty(); assert_eq!(a.swap(Box::new(1u8)), None); assert_eq!(a.swap(Box::new(2u8)), Some(Box::new(1u8))); assert_eq!(a.swap(Box::new(3u8)), Some(Box::new(2u8))); } #[test] fn take() { let a = Atom::new(Box::new(7u8)); assert_eq!(a.take(), Some(Box::new(7))); assert_eq!(a.take(), None); } #[test] fn set_if_none() { let a = Atom::empty(); assert_eq!(a.set_if_none(Box::new(7u8)), None); assert_eq!(a.set_if_none(Box::new(8u8)), Some(Box::new(8u8))); } #[derive(Clone)] struct Canary(Arc); impl Drop for Canary { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } #[test] fn ensure_drop() { let v = Arc::new(AtomicUsize::new(0)); let a = Box::new(Canary(v.clone())); let a = Atom::new(a); assert_eq!(v.load(Ordering::SeqCst), 0); drop(a); assert_eq!(v.load(Ordering::SeqCst), 1); } #[test] fn ensure_drop_arc() { let v = Arc::new(AtomicUsize::new(0)); let a = Arc::new(Canary(v.clone())); let a = Atom::new(a); assert_eq!(v.load(Ordering::SeqCst), 0); drop(a); assert_eq!(v.load(Ordering::SeqCst), 1); } #[test] fn ensure_send() { let atom = Arc::new(Atom::empty()); let wait = Arc::new(Barrier::new(2)); let w = wait.clone(); let a = atom.clone(); thread::spawn(move || { a.swap(Box::new(7u8)); w.wait(); }); wait.wait(); assert_eq!(atom.take(), Some(Box::new(7u8))); } #[test] fn get() { let atom = Arc::new(AtomSetOnce::empty()); assert_eq!(atom.get(), None); assert_eq!(atom.set_if_none(Box::new(8u8)), None); assert_eq!(atom.get(), Some(&8u8)); } #[test] fn get_arc() { let atom = Arc::new(AtomSetOnce::empty()); assert_eq!(atom.get(), None); assert_eq!(atom.set_if_none(Arc::new(8u8)), None); assert_eq!(atom.get(), Some(&8u8)); let v = Arc::new(AtomicUsize::new(0)); let atom = Arc::new(AtomSetOnce::empty()); atom.get(); atom.set_if_none(Arc::new(Canary(v.clone()))); atom.get(); drop(atom); assert_eq!(v.load(Ordering::SeqCst), 1); } #[derive(Debug)] struct Link { next: Option>, value: u32 } impl Link { fn new(v: u32) -> Box { Box::new(Link{ next: None, value: v }) } } impl GetNextMut for Box { type NextPtr = Option>; fn get_next(&mut self) -> &mut Option> { &mut self.next } } #[test] fn lifo() { let atom = Atom::empty(); for i in 0..100 { let x = atom.replace_and_set_next(Link::new(99-i)); assert_eq!(x, i == 0); } let expected: Vec = (0..100).collect(); let mut found = Vec::new(); let mut chain = atom.take(); while let Some(v) = chain { found.push(v.value); chain = v.next; } assert_eq!(expected, found); } #[allow(dead_code)] struct LinkCanary { next: Option>, value: Canary } impl LinkCanary { fn new(v: Canary) -> Box { Box::new(LinkCanary{ next: None, value: v }) } } impl GetNextMut for Box { type NextPtr = Option>; fn get_next(&mut self) -> &mut Option> { &mut self.next } } #[test] fn lifo_drop() { let v = Arc::new(AtomicUsize::new(0)); let canary = Canary(v.clone()); let mut link = LinkCanary::new(canary.clone()); link.next = Some(LinkCanary::new(canary.clone())); let atom = Atom::empty(); atom.replace_and_set_next(link); assert_eq!(1, v.load(Ordering::SeqCst)); drop(atom); assert_eq!(2, v.load(Ordering::SeqCst)); }