#![deny(warnings)] extern crate futures; extern crate tokio_mock_task; extern crate tokio_sync; use tokio_mock_task::*; use tokio_sync::semaphore::{Permit, Semaphore}; macro_rules! assert_ready { ($e:expr) => {{ match $e { Ok(futures::Async::Ready(v)) => v, Ok(_) => panic!("not ready"), Err(e) => panic!("error = {:?}", e), } }}; } macro_rules! assert_not_ready { ($e:expr) => {{ match $e { Ok(futures::Async::NotReady) => {} Ok(futures::Async::Ready(v)) => panic!("ready; value = {:?}", v), Err(e) => panic!("error = {:?}", e), } }}; } #[test] fn available_permits() { let s = Semaphore::new(100); assert_eq!(s.available_permits(), 100); // Polling for a permit succeeds immediately let mut permit = Permit::new(); assert!(!permit.is_acquired()); assert_ready!(permit.poll_acquire(&s)); assert_eq!(s.available_permits(), 99); assert!(permit.is_acquired()); // Polling again on the same waiter does not claim a new permit assert_ready!(permit.poll_acquire(&s)); assert_eq!(s.available_permits(), 99); assert!(permit.is_acquired()); } #[test] fn unavailable_permits() { let s = Semaphore::new(1); let mut permit_1 = Permit::new(); let mut permit_2 = Permit::new(); // Acquire the first permit assert_ready!(permit_1.poll_acquire(&s)); assert_eq!(s.available_permits(), 0); let mut task = MockTask::new(); task.enter(|| { // Try to acquire the second permit assert_not_ready!(permit_2.poll_acquire(&s)); }); permit_1.release(&s); assert_eq!(s.available_permits(), 0); assert!(task.is_notified()); assert_ready!(permit_2.poll_acquire(&s)); permit_2.release(&s); assert_eq!(s.available_permits(), 1); } #[test] fn zero_permits() { let s = Semaphore::new(0); assert_eq!(s.available_permits(), 0); let mut permit = Permit::new(); let mut task = MockTask::new(); // Try to acquire the permit task.enter(|| { assert_not_ready!(permit.poll_acquire(&s)); }); s.add_permits(1); assert!(task.is_notified()); assert_ready!(permit.poll_acquire(&s)); } #[test] #[should_panic] fn validates_max_permits() { use std::usize; Semaphore::new((usize::MAX >> 2) + 1); } #[test] fn close_semaphore_prevents_acquire() { let s = Semaphore::new(1); s.close(); assert_eq!(1, s.available_permits()); let mut permit = Permit::new(); assert!(permit.poll_acquire(&s).is_err()); assert_eq!(1, s.available_permits()); } #[test] fn close_semaphore_notifies_permit1() { let s = Semaphore::new(0); let mut permit = Permit::new(); let mut task = MockTask::new(); task.enter(|| { assert_not_ready!(permit.poll_acquire(&s)); }); s.close(); assert!(task.is_notified()); assert!(permit.poll_acquire(&s).is_err()); } #[test] fn close_semaphore_notifies_permit2() { let s = Semaphore::new(2); let mut permit1 = Permit::new(); let mut permit2 = Permit::new(); let mut permit3 = Permit::new(); let mut permit4 = Permit::new(); // Acquire a couple of permits assert_ready!(permit1.poll_acquire(&s)); assert_ready!(permit2.poll_acquire(&s)); let mut task1 = MockTask::new(); let mut task2 = MockTask::new(); task1.enter(|| { assert_not_ready!(permit3.poll_acquire(&s)); }); task2.enter(|| { assert_not_ready!(permit4.poll_acquire(&s)); }); s.close(); assert!(task1.is_notified()); assert!(task2.is_notified()); assert!(permit3.poll_acquire(&s).is_err()); assert!(permit4.poll_acquire(&s).is_err()); assert_eq!(0, s.available_permits()); permit1.release(&s); assert_eq!(1, s.available_permits()); assert!(permit1.poll_acquire(&s).is_err()); permit2.release(&s); assert_eq!(2, s.available_permits()); }