Skip to content

Commit

Permalink
Merge pull request #18 from wack/robbie/lints
Browse files Browse the repository at this point in the history
chore: Squash lints and add unit test for histogram total.
  • Loading branch information
RobbieMcKinstry authored Nov 8, 2024
2 parents 1a75841 + 1d13b0f commit 9b99446
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 69 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/on-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@ jobs:

- name: "Upload Coverage"
uses: coverallsapp/github-action@v2
with:
git-branch: "${{ github.base_ref || github.event.merge_group.base_ref }}"
66 changes: 2 additions & 64 deletions src/metrics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,3 @@
use crate::stats::Categorical;
use std::fmt;
pub use status_code::ResponseStatusCode;

/// [ResponseStatusCode] groups HTTP response status codes according
/// to five general categories. This type is used as the dependent
/// variable in statical observations.
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum ResponseStatusCode {
// Information responses
_1XX,
// Successful responses
_2XX,
// Redirection messages
_3XX,
// Client error responses
_4XX,
// Server error responses
_5XX,
}

impl Categorical<5> for ResponseStatusCode {
fn category(&self) -> usize {
match self {
Self::_1XX => 0,
Self::_2XX => 1,
Self::_3XX => 2,
Self::_4XX => 3,
Self::_5XX => 4,
}
}
}

impl fmt::Display for ResponseStatusCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::_1XX => write!(f, "1XX"),
Self::_2XX => write!(f, "2XX"),
Self::_3XX => write!(f, "3XX"),
Self::_4XX => write!(f, "4XX"),
Self::_5XX => write!(f, "5XX"),
}
}
}

#[cfg(test)]
mod tests {
use super::ResponseStatusCode;
use pretty_assertions::assert_str_eq;

#[test]
fn fmt_response_status_code() {
let test_cases = [
(ResponseStatusCode::_1XX, "1XX"),
(ResponseStatusCode::_2XX, "2XX"),
(ResponseStatusCode::_3XX, "3XX"),
(ResponseStatusCode::_4XX, "4XX"),
(ResponseStatusCode::_5XX, "5XX"),
];

for (input, expected) in test_cases {
let observed = input.to_string();
assert_str_eq!(expected, observed);
}
}
}
mod status_code;
66 changes: 66 additions & 0 deletions src/metrics/status_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::fmt;

use crate::stats::Categorical;

/// [ResponseStatusCode] groups HTTP response status codes according
/// to five general categories. This type is used as the dependent
/// variable in statical observations.
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum ResponseStatusCode {
// Information responses
_1XX,
// Successful responses
_2XX,
// Redirection messages
_3XX,
// Client error responses
_4XX,
// Server error responses
_5XX,
}

impl Categorical<5> for ResponseStatusCode {
fn category(&self) -> usize {
match self {
Self::_1XX => 0,
Self::_2XX => 1,
Self::_3XX => 2,
Self::_4XX => 3,
Self::_5XX => 4,
}
}
}

impl fmt::Display for ResponseStatusCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::_1XX => write!(f, "1XX"),
Self::_2XX => write!(f, "2XX"),
Self::_3XX => write!(f, "3XX"),
Self::_4XX => write!(f, "4XX"),
Self::_5XX => write!(f, "5XX"),
}
}
}

#[cfg(test)]
mod tests {
use super::ResponseStatusCode;
use pretty_assertions::assert_str_eq;

#[test]
fn fmt_response_status_code() {
let test_cases = [
(ResponseStatusCode::_1XX, "1XX"),
(ResponseStatusCode::_2XX, "2XX"),
(ResponseStatusCode::_3XX, "3XX"),
(ResponseStatusCode::_4XX, "4XX"),
(ResponseStatusCode::_5XX, "5XX"),
];

for (input, expected) in test_cases {
let observed = input.to_string();
assert_str_eq!(expected, observed);
}
}
}
2 changes: 1 addition & 1 deletion src/stats/categorical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// If modeling a six sided die, the groups would be 0 through 5, so N=6.
/// Each instance must be able to report which category it belongs to (using Self::category method).
/// Categories are zero-indexed (the first category is represented by `0usize`).
/// You can think of an [EnumerableCategory] as a hashmap with fixed integer keys. When the map is
/// You can think of a [Categorical] as a hashmap with fixed integer keys. When the map is
/// created, its keys must already be known and completely cover the range `[0, N)`.
///
/// ```rust
Expand Down
19 changes: 16 additions & 3 deletions src/stats/histogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::marker::PhantomData;
use super::Categorical;

/// [Histogram] is a data structure for tracking categorical observations.
/// In essence, its a map from Category to count.
/// In essence, it's a map from Category to count.
/// A [Histogram] has a fixed number of bins, each representing on of `N`
/// categories. Each time an member of the category is observed, it is
/// "added to the bin", incrementing the counter.
Expand Down Expand Up @@ -45,9 +45,10 @@ where
self.bins[index]
}

// TODO: Add a unit test for this function.
/// return the total number of observations in the histogram.
/// This is the sum of the counts across all bins.
pub fn total(&self) -> usize {
self.bins.iter().fold(0, |acc, n| acc + n)
self.bins.iter().sum::<usize>()
}

/// Reset all bins to zero.
Expand All @@ -67,6 +68,8 @@ where

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;

use crate::stats::Categorical;

use super::Histogram;
Expand All @@ -80,6 +83,16 @@ mod tests {
}
}

#[test]
fn histogram_total() {
let mut hist = Histogram::new();
hist.increment_by(&true, 15);
hist.increment_by(&false, 45);
let expected = 15 + 45;
let observed = hist.total();
assert_eq!(expected, observed);
}

/// This simple smoke test demonstrates that we can enumerable
/// simple categories, like booleans.
#[test]
Expand Down
5 changes: 4 additions & 1 deletion src/stats/tables/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ where
/// Construct a new, empty contingency table. All frequencies are
/// initialized to zero.
pub fn new() -> Self {
Self::default()
Self {
hist: Histogram::default(),
experimental_total: 0,
}
}

pub fn increment(&mut self, cat: &C) {
Expand Down

0 comments on commit 9b99446

Please sign in to comment.