proxy: Add histogram unit tests (#870)

This PR adds the unit tests for the proxy metrics module's Histogram 
implementation that I wrote in #775 to @olix0r's Histogram implementation
added in #868. The tests weren't too difficult to adapt for the new code,
and everything seems to work correctly!

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
Eliza Weisman 2018-04-27 17:02:13 -07:00 committed by GitHub
parent cf470439ef
commit aeaf1bf072
1 changed files with 130 additions and 0 deletions

View File

@ -123,3 +123,133 @@ impl cmp::Ord for Bucket {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use std::u64;
const NUM_BUCKETS: usize = 47;
static BOUNDS: &'static Bounds = &Bounds(&[
Bucket::Le(10),
Bucket::Le(20),
Bucket::Le(30),
Bucket::Le(40),
Bucket::Le(50),
Bucket::Le(60),
Bucket::Le(70),
Bucket::Le(80),
Bucket::Le(90),
Bucket::Le(100),
Bucket::Le(200),
Bucket::Le(300),
Bucket::Le(400),
Bucket::Le(500),
Bucket::Le(600),
Bucket::Le(700),
Bucket::Le(800),
Bucket::Le(900),
Bucket::Le(1_000),
Bucket::Le(2_000),
Bucket::Le(3_000),
Bucket::Le(4_000),
Bucket::Le(5_000),
Bucket::Le(6_000),
Bucket::Le(7_000),
Bucket::Le(8_000),
Bucket::Le(9_000),
Bucket::Le(10_000),
Bucket::Le(20_000),
Bucket::Le(30_000),
Bucket::Le(40_000),
Bucket::Le(50_000),
Bucket::Le(60_000),
Bucket::Le(70_000),
Bucket::Le(80_000),
Bucket::Le(90_000),
Bucket::Le(100_000),
Bucket::Le(200_000),
Bucket::Le(300_000),
Bucket::Le(400_000),
Bucket::Le(500_000),
Bucket::Le(600_000),
Bucket::Le(700_000),
Bucket::Le(800_000),
Bucket::Le(900_000),
Bucket::Le(1_000_000),
Bucket::Inf,
]);
quickcheck! {
fn bucket_incremented(obs: u64) -> bool {
let mut hist = Histogram::new(&BOUNDS);
hist.add(obs);
let incremented_bucket = &BOUNDS.0.iter()
.position(|bucket| match *bucket {
Bucket::Le(ceiling) => obs <= ceiling,
Bucket::Inf => true,
})
.unwrap();
for i in 0..NUM_BUCKETS {
let expected = if i == *incremented_bucket { 1 } else { 0 };
let count: u64 = hist.buckets[i].into();
assert_eq!(count, expected, "(for bucket <= {})", BOUNDS.0[i]);
}
true
}
fn sum_equals_total_of_observations(observations: Vec<u64>) -> bool {
let mut hist = Histogram::new(&BOUNDS);
let mut expected_sum = Wrapping(0u64);
for obs in observations {
expected_sum += Wrapping(obs);
hist.add(obs);
}
hist.sum == expected_sum
}
fn count_equals_number_of_observations(observations: Vec<u64>) -> bool {
let mut hist = Histogram::new(&BOUNDS);
for obs in &observations {
hist.add(*obs);
}
let count: u64 = hist.buckets.iter().map(|&c| {
let count: u64 = c.into();
count
}).sum();
count as usize == observations.len()
}
fn multiple_observations_increment_buckets(observations: Vec<u64>) -> bool {
let mut buckets_and_counts: HashMap<usize, u64> = HashMap::new();
let mut hist = Histogram::new(&BOUNDS);
for obs in observations {
let incremented_bucket = &BOUNDS.0.iter()
.position(|bucket| match *bucket {
Bucket::Le(ceiling) => obs <= ceiling,
Bucket::Inf => true,
})
.unwrap();
*buckets_and_counts
.entry(*incremented_bucket)
.or_insert(0) += 1;
hist.add(obs);
}
for (i, count) in hist.buckets.iter().enumerate() {
let count: u64 = (*count).into();
assert_eq!(buckets_and_counts.get(&i).unwrap_or(&0), &count);
}
true
}
}
}