use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Assertion {
Equals(f64),
NotEquals(f64),
GreaterThan(f64),
GreaterThanOrEqual(f64),
LessThan(f64),
LessThanOrEqual(f64),
Between(f64, f64),
NotBetween(f64, f64),
}
impl Assertion {
pub fn evaluate(&self, value: f64) -> bool {
const EPSILON: f64 = 1e-10;
match self {
Assertion::Equals(expected) => (value - expected).abs() < EPSILON,
Assertion::NotEquals(expected) => (value - expected).abs() >= EPSILON,
Assertion::GreaterThan(threshold) => value > *threshold,
Assertion::GreaterThanOrEqual(threshold) => value >= *threshold,
Assertion::LessThan(threshold) => value < *threshold,
Assertion::LessThanOrEqual(threshold) => value <= *threshold,
Assertion::Between(min, max) => value >= *min && value <= *max,
Assertion::NotBetween(min, max) => value < *min || value > *max,
}
}
pub fn description(&self) -> String {
match self {
Assertion::Equals(v) => format!("equals {v}"),
Assertion::NotEquals(v) => format!("not equals {v}"),
Assertion::GreaterThan(v) => format!("greater than {v}"),
Assertion::GreaterThanOrEqual(v) => format!("greater than or equal to {v}"),
Assertion::LessThan(v) => format!("less than {v}"),
Assertion::LessThanOrEqual(v) => format!("less than or equal to {v}"),
Assertion::Between(min, max) => format!("between {min} and {max}"),
Assertion::NotBetween(min, max) => format!("not between {min} and {max}"),
}
}
}
impl fmt::Display for Assertion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.description())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_equals() {
let assertion = Assertion::Equals(10.0);
assert!(assertion.evaluate(10.0));
assert!(!assertion.evaluate(10.1));
}
#[test]
fn test_not_equals() {
let assertion = Assertion::NotEquals(10.0);
assert!(!assertion.evaluate(10.0));
assert!(assertion.evaluate(10.1));
}
#[test]
fn test_greater_than() {
let assertion = Assertion::GreaterThan(10.0);
assert!(assertion.evaluate(10.1));
assert!(!assertion.evaluate(10.0));
assert!(!assertion.evaluate(9.9));
}
#[test]
fn test_between() {
let assertion = Assertion::Between(10.0, 20.0);
assert!(assertion.evaluate(15.0));
assert!(assertion.evaluate(10.0));
assert!(assertion.evaluate(20.0));
assert!(!assertion.evaluate(9.9));
assert!(!assertion.evaluate(20.1));
}
#[test]
fn test_description() {
assert_eq!(Assertion::Equals(10.0).description(), "equals 10");
assert_eq!(Assertion::GreaterThan(5.0).description(), "greater than 5");
assert_eq!(
Assertion::Between(1.0, 10.0).description(),
"between 1 and 10"
);
}
}