tokio/tokio-sync/tests/semaphore.rs
2019-02-21 11:56:15 -08:00

177 lines
3.9 KiB
Rust

#![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());
}