<commit_before>extern crate ratelimit_meter;
#[macro_use]
extern crate nonzero_ext;

use ratelimit_meter::{DirectRateLimiter, LeakyBucket, NegativeMultiDecision, NonConformance};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    assert_eq!(Ok(()), lb.check());
}

#[test]
fn rejects_too_many() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(2u32));
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), lb.check_at(now));
    assert_eq!(Ok(()), lb.check_at(now));
    assert!(!lb.check_at(now + ms * 2).is_ok());
    // should be ok again in 1s:
    let next = now + Duration::from_millis(1002);
    assert_eq!(Ok(()), lb.check_at(next));
    assert_eq!(Ok(()), lb.check_at(next + ms));
    assert!(!lb.check_at(next + ms * 2).is_ok(), "{:?}", lb);
}

#[test]
fn never_allows_more_than_capacity() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert!(lb.check_n_at(15, now).is_err());

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert!(lb.check_n_at(15, now + (ms * 3 * 1000)).is_err());

    let result = lb.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn correct_wait_time() {
    // Bucket adding a new element per 200ms:
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    let mut now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut conforming = 0;
    for _i in 0..20 {
        now += ms;
        let res = lb.check_at(now);
        match res {
            Ok(()) => {<commit_msg>Preliminary leaky bucket test refactoring<commit_after>extern crate ratelimit_meter;
#[macro_use]
extern crate nonzero_ext;

use ratelimit_meter::{DirectRateLimiter, LeakyBucket, NegativeMultiDecision, NonConformance};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    assert_eq!(Ok(()), lb.check_at(Instant::now()));
}

#[test]
fn rejects_too_many() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(2u32));
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), lb.check_at(now));
    assert_eq!(Ok(()), lb.check_at(now));

    assert_ne!(Ok(()), lb.check_at(now + ms * 2));

    // should be ok again in 1s:
    let next = now + Duration::from_millis(1002);
    assert_eq!(Ok(()), lb.check_at(next));
    assert_eq!(Ok(()), lb.check_at(next + ms));

    assert_ne!(Ok(()), lb.check_at(next + ms * 2), "{:?}", lb);
}

#[test]
fn never_allows_more_than_capacity() {
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert_ne!(Ok(()), lb.check_n_at(15, now));

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert_ne!(Ok(()), lb.check_n_at(15, now + (ms * 3 * 1000)));
    let result = lb.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn correct_wait_time() {
    // Bucket adding a new element per 200ms:
    let mut lb = DirectRateLimiter::<LeakyBucket>::per_second(nonzero!(5u32));
    let mut now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut conforming = 0;
    for _i in 0..20 {
        now += ms;
        let res = lb.check_at(now);
        match res {
            Ok(()) => {
{'fraction_non_alphanumeric': 0.17196353781719637, 'fraction_numerical': 0.0275930032027593, 'mean_word_length': 3.8739495798319328, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '77614', 'n_tokens_mistral': 1514, 'n_tokens_neox': 1411, 'n_words': 336}