Spaces:
Running
Running
| import unittest | |
| import uuid | |
| from src.session_recommendation import image_sha256, update_session_recommendation | |
| def multi_result(*, handedness="Right", index=1.80, middle=1.90, ring=1.70): | |
| values = {"index": index, "middle": middle, "ring": ring} | |
| per_finger = {} | |
| for finger, value in values.items(): | |
| if value is None: | |
| per_finger[finger] = { | |
| "status": "failed", | |
| "diameter_cm": None, | |
| "best_match": None, | |
| "range": None, | |
| "fail_reason": "finger_isolation_failed", | |
| } | |
| else: | |
| per_finger[finger] = { | |
| "status": "ok", | |
| "diameter_cm": value, | |
| "best_match": 8, | |
| "range": [7, 8], | |
| "fail_reason": None, | |
| } | |
| return { | |
| "fail_reason": None, | |
| "handedness": handedness, | |
| "per_finger": per_finger, | |
| "fingers_measured": 3, | |
| "fingers_succeeded": sum(v is not None for v in values.values()), | |
| } | |
| class SessionRecommendationTests(unittest.TestCase): | |
| def setUp(self): | |
| self.session_id = str(uuid.uuid4()) | |
| def update(self, state, result, image, **kwargs): | |
| return update_session_recommendation( | |
| state, | |
| session_id=self.session_id, | |
| ring_model=kwargs.get("ring_model", "gen"), | |
| run_id=kwargs.get("run_id", image), | |
| image_digest=image_sha256(image.encode()), | |
| result=result, | |
| mode=kwargs.get("mode", "multi"), | |
| finger_index=kwargs.get("finger_index", "index"), | |
| ) | |
| def test_first_shot_matches_its_diameter(self): | |
| state, rec = self.update(None, multi_result(index=1.80), "one") | |
| self.assertEqual(state["attempt_count"], 1) | |
| self.assertEqual(rec["per_finger"]["index"]["diameter_cm"], 1.80) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 1) | |
| def test_even_and_odd_medians_are_computed_before_size_lookup(self): | |
| state, _ = self.update(None, multi_result(index=1.70), "one") | |
| state, rec = self.update(state, multi_result(index=1.90), "two") | |
| self.assertEqual(rec["per_finger"]["index"]["diameter_cm"], 1.80) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 2) | |
| state, rec = self.update(state, multi_result(index=1.80), "three") | |
| self.assertEqual(rec["per_finger"]["index"]["diameter_cm"], 1.80) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 3) | |
| def test_size_lookup_rounds_median_to_tenth_mm_and_prefers_smaller_tie(self): | |
| state, _ = self.update( | |
| None, | |
| multi_result(index=1.7784), | |
| "one", | |
| ring_model="air", | |
| ) | |
| _, rec = self.update( | |
| state, | |
| multi_result(index=1.7837), | |
| "two", | |
| ring_model="air", | |
| ) | |
| index = rec["per_finger"]["index"] | |
| self.assertEqual(index["diameter_cm"], 1.78105) | |
| self.assertEqual(index["decision_diameter_mm"], 17.8) | |
| self.assertEqual(index["best_match"], 7) | |
| def test_nearby_medians_on_both_sides_share_the_same_air_decision(self): | |
| _, above = self.update( | |
| None, | |
| multi_result(index=1.7807), | |
| "above", | |
| ring_model="air", | |
| ) | |
| self.session_id = str(uuid.uuid4()) | |
| _, below = self.update( | |
| None, | |
| multi_result(index=1.7795), | |
| "below", | |
| ring_model="air", | |
| ) | |
| for rec in (above, below): | |
| index = rec["per_finger"]["index"] | |
| self.assertEqual(index["decision_diameter_mm"], 17.8) | |
| self.assertEqual(index["best_match"], 7) | |
| def test_partial_failure_only_skips_that_finger(self): | |
| state, rec = self.update(None, multi_result(index=1.80, middle=None), "one") | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 1) | |
| self.assertEqual(rec["per_finger"]["middle"]["status"], "failed") | |
| self.assertEqual(rec["per_finger"]["middle"]["sample_count"], 0) | |
| def test_duplicate_image_is_not_counted_twice(self): | |
| state, _ = self.update(None, multi_result(index=1.80), "same") | |
| state, rec = self.update(state, multi_result(index=1.80), "same") | |
| self.assertEqual(state["attempt_count"], 2) | |
| self.assertEqual(len(state["shots"]), 1) | |
| self.assertTrue(rec["duplicate_image"]) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 1) | |
| def test_hands_are_partitioned(self): | |
| state, _ = self.update(None, multi_result(handedness="Right", index=1.80), "right") | |
| state, rec = self.update(state, multi_result(handedness="Left", index=2.00), "left") | |
| self.assertEqual(rec["handedness"], "Left") | |
| self.assertEqual(rec["per_finger"]["index"]["diameter_cm"], 2.00) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 1) | |
| def test_total_failure_increments_attempt_without_stale_recommendation(self): | |
| state, _ = self.update(None, multi_result(index=1.80), "one") | |
| failed = {"fail_reason": "card_not_detected", "per_finger": {}} | |
| state, rec = self.update(state, failed, "two") | |
| self.assertEqual(state["attempt_count"], 2) | |
| self.assertEqual(len(state["shots"]), 1) | |
| self.assertIsNone(rec) | |
| def test_single_mode_uses_same_aggregator(self): | |
| first = { | |
| "fail_reason": None, | |
| "handedness": "Right", | |
| "finger_outer_diameter_cm": 1.70, | |
| } | |
| second = {**first, "finger_outer_diameter_cm": 1.90} | |
| state, _ = self.update(None, first, "one", mode="single") | |
| _, rec = self.update(state, second, "two", mode="single") | |
| self.assertEqual(rec["finger_outer_diameter_cm"], 1.80) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 2) | |
| def test_mismatched_or_malformed_state_starts_fresh(self): | |
| malformed = { | |
| "version": 1, | |
| "session_id": str(uuid.uuid4()), | |
| "ring_model": "gen", | |
| "attempt_count": 999, | |
| "shots": [{"diameter_cm": "hacked"}], | |
| } | |
| state, rec = self.update(malformed, multi_result(index=1.80), "one") | |
| self.assertEqual(state["attempt_count"], 1) | |
| self.assertEqual(len(state["shots"]), 1) | |
| self.assertEqual(rec["per_finger"]["index"]["sample_count"], 1) | |
| if __name__ == "__main__": | |
| unittest.main() | |