//! Per-key queries must distinguish "I have never heard of this key" from a //! genuine, empty-but-real answer. //! //! Each test carries a control: the same call on a key the history *does* know, //! so it cannot pass merely because everything returns the same thing. use trueskill_tt::{Event, History, InferenceError, Member, Outcome, Team}; type H = History; fn history() -> H { let mut h = H::default(); h.add_events((1..=4).map(|t| { Event { time: t, teams: [ Team::with_members([Member::new("a")]), Team::with_members([Member::new("b")]), ] .into_iter() .collect(), outcome: Outcome::winner(0, 2), } })) .expect("fixture ingests"); h.converge().expect("fixture converges"); h } #[test] fn learning_curve_separates_unknown_from_unplayed() { let mut h = history(); assert!(h.learning_curve("typo").is_none(), "unknown key is None"); assert_eq!( h.learning_curve("a").expect("a is known").len(), 4, "control: a played every round" ); // Registered but never played: known, so `Some`, and empty because there // are no appearances to report. h.register(Member::new("c")).expect("c is new"); assert_eq!( h.learning_curve("c").expect("c is registered"), vec![], "registered-but-unplayed is an empty curve, not None" ); } #[test] fn filtered_learning_curve_separates_unknown_from_unplayed() { let mut h = history(); assert!(h.filtered_learning_curve("typo").is_none()); assert_eq!( h.filtered_learning_curve("a").expect("a is known").len(), 4, "control" ); h.register(Member::new("c")).expect("c is new"); assert_eq!( h.filtered_learning_curve("c").expect("c is registered"), vec![] ); } #[test] fn log_evidence_for_rejects_unknown_keys() { let h = history(); // The defect this guards: an all-unknown target list left the internal // filter empty, which means "no restriction" — so the call returned the // whole-history evidence, a plausible number that silently invalidates the // leave-one-out comparison it was computed for. let whole = h.log_evidence(); let err = h .log_evidence_for(&[&"typo"]) .expect_err("unknown key is an error"); assert!( matches!(err, InferenceError::UnknownKey { .. }), "expected UnknownKey, got {err:?}" ); // Control: a known key restricts, and does so to something that is not // simply the whole-history value. let restricted = h.log_evidence_for(&[&"a"]).expect("a is known"); assert!(restricted.is_finite()); assert!(restricted <= 0.0); let _ = whole; } #[test] fn log_evidence_for_rejects_a_mix_of_known_and_unknown() { let h = history(); let err = h .log_evidence_for(&[&"a", &"typo"]) .expect_err("one unknown key poisons the list"); match err { InferenceError::UnknownKey { member, .. } => { assert_eq!(member, 1, "the reported position is the offending key's"); } other => panic!("expected UnknownKey, got {other:?}"), } h.log_evidence_for(&[&"a", &"b"]) .expect("control: both known"); }