test(server): add unit tests for hash_date_to_u64 and generate_goal

The daily-challenge seed function had no unit test coverage. Added tests
for determinism, cross-day and cross-year distinctness, non-zero output,
and all six generate_goal variants (score/time field correctness).
This acts as a change-detection guard for the authoritative seed algorithm
that all players worldwide rely on to receive the same daily deal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-04-27 04:00:08 +00:00
parent 2dd5b1fc9c
commit 96ac44fbef
+61
View File
@@ -134,3 +134,64 @@ pub async fn daily_challenge(
Ok(Json(goal))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hash_date_is_deterministic() {
let date = "2026-04-26";
assert_eq!(hash_date_to_u64(date), hash_date_to_u64(date));
}
#[test]
fn hash_date_differs_across_adjacent_days() {
assert_ne!(hash_date_to_u64("2026-04-26"), hash_date_to_u64("2026-04-27"));
assert_ne!(hash_date_to_u64("2026-04-26"), hash_date_to_u64("2026-04-25"));
}
#[test]
fn hash_date_differs_across_years() {
assert_ne!(hash_date_to_u64("2026-01-01"), hash_date_to_u64("2027-01-01"));
}
#[test]
fn hash_date_is_nonzero_for_real_dates() {
// Zero would be pathological — every date must produce a non-zero seed
// so the RNG initialises properly.
assert_ne!(hash_date_to_u64("2026-04-26"), 0);
assert_ne!(hash_date_to_u64("2026-01-01"), 0);
}
#[test]
fn generate_goal_covers_all_six_variants() {
// The six variants are selected by seed % 6. Verify each branch
// produces a non-empty description and a non-empty date string.
for variant_idx in 0u64..6 {
let goal = generate_goal("2026-04-26", variant_idx);
assert_eq!(goal.date, "2026-04-26");
assert!(!goal.description.is_empty());
// seed field must match the passed-in seed.
assert_eq!(goal.seed, variant_idx);
}
}
#[test]
fn generate_goal_time_and_score_variants_are_set_correctly() {
// Variant 0: max_time_secs = 300, no score.
let g = generate_goal("2026-04-26", 0);
assert_eq!(g.max_time_secs, Some(300));
assert!(g.target_score.is_none());
// Variant 1: target_score = 4000, no time.
let g = generate_goal("2026-04-26", 1);
assert_eq!(g.target_score, Some(4_000));
assert!(g.max_time_secs.is_none());
// Variant 5: fallback — no time, no score (just win).
let g = generate_goal("2026-04-26", 5);
assert!(g.target_score.is_none());
assert!(g.max_time_secs.is_none());
}
}