Spaces:
Running
Running
File size: 6,484 Bytes
9f6a8e2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | 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()
|