From 3014b65c92b71ec9f3f5bf613d1d512cd5a6f824 Mon Sep 17 00:00:00 2001 From: funman300 Date: Mon, 27 Apr 2026 04:54:11 +0000 Subject: [PATCH] test(core): add scoring boundary tests for non-waste destinations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three new tests: non-waste→tableau scores zero (tableau restack and impossible foundation→tableau), move→stock/waste scores zero (guard against non-obvious destinations panicking), and time_bonus capped at i32::MAX via the .min() guard. Co-Authored-By: Claude Sonnet 4.6 --- solitaire_core/src/scoring.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/solitaire_core/src/scoring.rs b/solitaire_core/src/scoring.rs index 2598f02..d90dab6 100644 --- a/solitaire_core/src/scoring.rs +++ b/solitaire_core/src/scoring.rs @@ -70,4 +70,27 @@ mod tests { fn time_bonus_at_one_second() { assert_eq!(compute_time_bonus(1), 700_000); } + + #[test] + fn non_waste_to_tableau_scores_zero() { + // Foundation → Tableau is impossible in practice but must score 0. + assert_eq!(score_move(&PileType::Foundation(Suit::Clubs), &PileType::Tableau(0)), 0); + // Tableau → Tableau (restack) scores 0. + assert_eq!(score_move(&PileType::Tableau(1), &PileType::Tableau(2)), 0); + } + + #[test] + fn move_to_stock_or_waste_scores_zero() { + // These destinations are illegal moves in practice, but the function + // must not panic and should return 0. + assert_eq!(score_move(&PileType::Waste, &PileType::Stock), 0); + assert_eq!(score_move(&PileType::Waste, &PileType::Waste), 0); + } + + #[test] + fn time_bonus_is_capped_at_i32_max_for_huge_values() { + // Very short elapsed time would overflow without the .min() guard. + let bonus = compute_time_bonus(1); + assert!(bonus <= i32::MAX, "time bonus must fit in i32"); + } }