#![cfg(feature = "std")]
use assertables::*;
use futures_executor::block_on;
use governor::{Quota, RateLimiter};
use nonzero_ext::*;
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
const MAX_TEST_RUN_DURATION: Duration = Duration::from_micros(200);
#[test]
fn pauses() {
let lim = RateLimiter::direct(Quota::per_second(nonzero!(10u32)));
loop {
if lim.check().is_err() {
break;
}
}
let i = Instant::now();
block_on(lim.until_ready());
assert_ge!(i.elapsed(), Duration::from_millis(100));
}
#[test]
fn pauses_n() {
let lim = RateLimiter::direct(Quota::per_second(nonzero!(10u32)));
for _ in 0..6 {
lim.check().unwrap();
}
let i = Instant::now();
block_on(lim.until_n_ready(nonzero!(5u32))).unwrap();
assert_ge!(i.elapsed(), Duration::from_millis(100));
}
#[test]
fn pauses_keyed() {
let i = Instant::now();
let lim = RateLimiter::keyed(Quota::per_second(nonzero!(10u32)));
loop {
if lim.check_key(&1u32).is_err() {
break;
}
}
block_on(lim.until_key_ready(&1u32));
assert_ge!(i.elapsed(), Duration::from_millis(100));
}
#[test]
fn pauses_keyed_n() {
let lim = RateLimiter::keyed(Quota::per_second(nonzero!(10u32)));
for _ in 0..6 {
lim.check_key(&1u32).unwrap();
}
let i = Instant::now();
block_on(lim.until_key_n_ready(&1u32, nonzero!(5u32))).unwrap();
assert_ge!(i.elapsed(), Duration::from_millis(100));
}
#[test]
fn proceeds() {
let lim = RateLimiter::direct(Quota::per_second(nonzero!(2u32)));
let i = Instant::now();
block_on(lim.until_ready());
assert_le!(i.elapsed(), MAX_TEST_RUN_DURATION);
}
#[test]
fn proceeds_n() {
let lim = RateLimiter::direct(Quota::per_second(nonzero!(3u32)));
let i = Instant::now();
block_on(lim.until_n_ready(nonzero!(2u32))).unwrap();
assert_le!(i.elapsed(), MAX_TEST_RUN_DURATION);
}
#[test]
fn proceeds_keyed() {
let lim = RateLimiter::keyed(Quota::per_second(nonzero!(2u32)));
let i = Instant::now();
block_on(lim.until_key_ready(&1u32));
assert_le!(i.elapsed(), MAX_TEST_RUN_DURATION);
}
#[test]
fn proceeds_keyed_n() {
let lim = RateLimiter::keyed(Quota::per_second(nonzero!(3u32)));
let i = Instant::now();
block_on(lim.until_key_n_ready(&1u32, nonzero!(2u32))).unwrap();
assert_le!(i.elapsed(), MAX_TEST_RUN_DURATION);
}
#[test]
fn multiple() {
let lim = Arc::new(RateLimiter::direct(Quota::per_second(nonzero!(10u32))));
let mut children = vec![];
let i = Instant::now();
for _i in 0..20 {
let lim = Arc::clone(&lim);
children.push(thread::spawn(move || {
block_on(lim.until_ready());
}));
}
for child in children {
child.join().unwrap();
}
let elapsed = i.elapsed();
assert_ge!(elapsed, Duration::from_millis(8),);
}
#[test]
fn multiple_keyed() {
let lim = Arc::new(RateLimiter::keyed(Quota::per_second(nonzero!(10u32))));
let mut children = vec![];
let i = Instant::now();
for _i in 0..20 {
let lim = Arc::clone(&lim);
children.push(thread::spawn(move || {
block_on(lim.until_key_ready(&1u32));
}));
}
for child in children {
child.join().unwrap();
}
let elapsed = i.elapsed();
assert_ge!(elapsed, Duration::from_millis(8),);
}
#[test]
fn errors_on_exceeded_capacity() {
let lim = RateLimiter::direct(Quota::per_second(nonzero!(10u32)));
block_on(lim.until_n_ready(nonzero!(11u32))).unwrap_err();
let lim = RateLimiter::keyed(Quota::per_second(nonzero!(10u32)));
block_on(lim.until_key_n_ready(&1u32, nonzero!(11u32))).unwrap_err();
}