score&test, Tests for a42853a & test_utils mod

Tests for all the core functionality implemented to score in a42853a.

Optimistically adding a test_utils mod for shared test code
This commit is contained in:
Julia Lange 2026-02-05 12:36:28 -08:00
parent 674079769d
commit fafb017f64
Signed by: Julia
SSH key fingerprint: SHA256:5DJcfxa5/fKCYn57dcabJa2vN2e6eT0pBerYi5SUbto
3 changed files with 211 additions and 0 deletions

View file

@ -3,6 +3,10 @@ use std::error::Error;
type Result<T> = std::result::Result<T, Box<dyn Error>>;
pub mod score;
#[cfg(test)]
pub mod test_utils;
pub struct AdapterPool(sqlx::SqlitePool);
pub struct AdapterBuilder {
database_url: String,

View file

@ -191,3 +191,199 @@ impl BoostedScore {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::get_datetime;
#[test]
fn gravity_default() {
let gravity = Gravity::new(None);
assert_eq!(i64::from(gravity), default::GRAVITY);
}
#[test]
fn boost_default() {
let boost = Boost::new(None);
assert_eq!(i64::from(boost), default::BOOST);
}
// "Score" Tests
#[test]
fn new() {
let score = TimedScore::new();
assert_eq!(score.value, Score(default::INITIAL_SCORE));
}
#[test]
fn new_with_values() {
let dt = get_datetime();
let score = TimedScore::new_with_initial_and_time(Score(10), dt);
assert_eq!(score.value, Score(10));
assert_eq!(score.last_updated, dt);
}
#[test]
fn update_score_stays_decaying() {
let dt = get_datetime();
let score = TimedScore::Decaying(
TimedScore::new_with_initial_and_time(Score(10), dt)
);
let gravity = Gravity::new(None);
let dt2 = dt + TimeDelta::seconds(SECONDS_IN_A_DAY);
score.update_score_at_time(gravity, dt2).get_decaying().unwrap();
}
#[test]
fn update_score_stays_frozen() {
let dt = get_datetime();
let score = TimedScore::Boosted(
BoostedScore { value: Score(10), boosted_at: dt }
);
let gravity = Gravity::new(None);
let dt2 = dt + TimeDelta::seconds(default::BOOST_FREEZE_IN_SECONDS);
score.update_score_at_time(gravity, dt2).get_boosted().unwrap();
}
#[test]
fn update_score_thaws_and_decays() {
let dt = get_datetime();
let score = TimedScore::Boosted(
BoostedScore { value: Score(10), boosted_at: dt }
);
let gravity = Gravity::new(None);
let dt2 = dt + TimeDelta::seconds(
default::BOOST_FREEZE_IN_SECONDS + SECONDS_IN_A_DAY
);
let updated = score.update_score_at_time(gravity, dt2)
.get_decaying().unwrap();
assert!(updated.value < Score(10))
}
#[test]
fn get_decaying_success() {
let dt = get_datetime();
let score = TimedScore::Decaying(
TimedScore::new_with_initial_and_time(Score(10), dt)
);
score.get_decaying().unwrap();
}
#[test]
#[should_panic = "Attempted to get_boosted() of a decaying score"]
fn get_boosted_failure() {
let dt = get_datetime();
let score = TimedScore::Decaying(
TimedScore::new_with_initial_and_time(Score(10), dt)
);
score.get_boosted().unwrap();
}
#[test]
#[should_panic = "Attempted to get_decaying() of a boosted score"]
fn get_decaying_failure() {
let dt = get_datetime();
let boost = Boost::new(None);
let score = TimedScore::Boosted(
TimedScore::new_with_initial_and_time(Score(10), dt)
.boost_at_time(boost, dt)
);
score.get_decaying().unwrap();
}
#[test]
fn get_boosted_success() {
let dt = get_datetime();
let boost = Boost::new(None);
let score = TimedScore::Boosted(
TimedScore::new_with_initial_and_time(Score(10), dt)
.boost_at_time(boost, dt)
);
score.get_boosted().unwrap();
}
// "DecayingScore" Tests
#[test]
fn apply_gravity_to_future() {
let dt = get_datetime();
let score = DecayingScore { value: Score(10), last_updated: dt };
let future = dt + TimeDelta::seconds(SECONDS_IN_A_DAY);
let gravity = Gravity::new(None);
let updated = score.apply_gravity_to_time(gravity, future);
assert!(updated.value < Score(10));
assert_eq!(updated.last_updated, future);
}
#[test]
fn apply_gravity_to_past() {
let dt = get_datetime();
let score = DecayingScore { value: Score(10), last_updated: dt };
let past = dt - TimeDelta::seconds(SECONDS_IN_A_DAY);
let gravity = Gravity::new(None);
let updated = score.apply_gravity_to_time(gravity, past);
assert!(updated.value > Score(10));
assert_eq!(updated.last_updated, past);
}
#[test]
fn boost() {
let dt = get_datetime();
let score = DecayingScore { value: Score(10), last_updated: dt };
let boost = Boost::new(None);
let boosted = score.boost_at_time(boost, dt);
assert_eq!(boosted.value, Score(10) + Boost(default::BOOST));
assert_eq!(boosted.boosted_at, dt);
}
// "BoostedScore" tests
#[test]
fn unboost() {
let dt = get_datetime();
let score = DecayingScore { value: Score(10), last_updated: dt };
let boost = Boost::new(None);
let boosted = score.boost_at_time(boost, dt);
let unboosted = boosted.unboost(boost);
assert_eq!(unboosted.value, Score(10));
assert_eq!(unboosted.last_updated, dt);
}
#[test]
fn boosted_stays_frozen() {
let dt = get_datetime();
let score = BoostedScore { value: Score(10), boosted_at: dt };
let last_second = dt + TimeDelta::seconds(default::BOOST_FREEZE_IN_SECONDS);
score.try_unfreeze_at_time(last_second).get_boosted().unwrap();
}
#[test]
fn boosted_thaws() {
let dt = get_datetime();
let score = BoostedScore { value: Score(10), boosted_at: dt };
let first_second = dt + TimeDelta::days(default::BOOST_FREEZE_IN_SECONDS+1);
score.try_unfreeze_at_time(first_second).get_decaying().unwrap();
}
}

11
koucha/src/test_utils.rs Normal file
View file

@ -0,0 +1,11 @@
#![cfg(test)]
use chrono::{
Utc,
TimeZone,
DateTime
};
pub fn get_datetime() -> DateTime<Utc> {
Utc.with_ymd_and_hms(2020,1,1,0,0,0).unwrap()
}