Files
vision-anti-pinch/tests/test_risk_integration.py
T

71 lines
3.8 KiB
Python

"""Behavior tests for CAN validity and upstream per-door evidence gating."""
import sys
import unittest
import tempfile
from pathlib import Path
import numpy as np
ROOT=Path(__file__).resolve().parents[1]
sys.path.insert(0,str(ROOT))
from run_camera import select_active_door,gate_risks,JsonlWriter
from door_mask_risk import DoorMaskSequence,DoorRiskEvaluator
from door_zone_risk import DoorZoneConfig,DoorZoneAssigner
from predict_optimized_pose_videos import BoxTracker
class CanTests(unittest.TestCase):
def test_four_bytes_and_side(self):
for front in [0,20]:
for rear in [0,30]:
for side in ['left','right']:
pos=[40]*4;i=0 if side=='left' else 1;pos[i]=front;pos[i+2]=rear
expected='both' if front==rear==0 else 'front' if front==0 else 'rear' if rear==0 else 'none'
self.assertEqual(select_active_door('can',{'positions':pos,'age_ms':10},side),(expected,True))
def test_invalid_never_becomes_clear(self):
for age in [-1,1001]:
active,valid=select_active_door('can',{'positions':[0]*4,'age_ms':age})
self.assertFalse(valid)
doors,risk=gate_risks({'regions':[]},[],active,valid)
self.assertEqual(risk['risk_level'],'unknown');self.assertIsNone(risk['risk_score'])
self.assertTrue(all(r['risk_level']=='unknown' for r in doors.values()))
def test_real_none_is_inactive(self):
active,valid=select_active_door('can',{'positions':[10]*4,'age_ms':0})
_,risk=gate_risks({'regions':[]},[],active,valid)
self.assertEqual(risk['risk_level'],'inactive')
class RiskTests(unittest.TestCase):
def setUp(self):
self.evaluator=DoorRiskEvaluator(DoorMaskSequence(constant_mask=ROOT/'annotations/constant_door_mask.json'))
def test_body_fallback_intersection_and_can_filter(self):
record={'boxes':[[0,0,1920,1536]],'track_ids':[42],'global_hands':[]}
raw,_=self.evaluator.evaluate(0,record,(1536,1920))
self.assertEqual(raw['risk_level'],'danger')
self.assertEqual(raw['regions'][0]['source'],'YOLO_BODY_BOX_FALLBACK')
assignments=[{'person_index':0,'track_id':42,'door_zone':'rear'}]
_,rear=gate_risks(raw,assignments,'rear',True)
_,front=gate_risks(raw,assignments,'front',True)
self.assertEqual(rear['risk_type'],'REAR_DANGER')
self.assertEqual(front['risk_type'],'FRONT_CLEAR')
def test_transition_keeps_unknown(self):
raw,_=self.evaluator.evaluate(0,{'boxes':[[0,0,1920,1536]],'track_ids':[42]},(1536,1920))
_,risk=gate_risks(raw,[{'person_index':0,'track_id':42,'door_zone':'transition'}],'front',True)
self.assertEqual(risk['risk_level'],'unknown');self.assertIsNone(risk['risk_score'])
def test_hand_overrides_whole_body_fallback(self):
hand={'person_id':1,'side':'left','keypoints':[[1,1],[50,1],[50,50],[1,50]]}
raw,_=self.evaluator.evaluate(0,{'boxes':[[0,0,1920,1536]],'track_ids':[42],'global_hands':[hand]},(1536,1920))
self.assertEqual(len(raw['regions']),1)
self.assertEqual(raw['regions'][0]['source'],'RTMW_HAND_KEYPOINTS')
def test_expired_tracker_state_pruned(self):
t=BoxTracker(max_age=30);t.update([[1,1,100,100]],0,(1536,1920));t.update([],31,(1536,1920))
self.assertEqual(t.tracks,{})
class OutputTests(unittest.TestCase):
def test_rotation_keeps_complete_utf8_records(self):
with tempfile.TemporaryDirectory() as tmp:
path=Path(tmp)/'risk.jsonl'
with JsonlWriter(path,19) as writer:
for i in range(6):writer.write('{"门":%d}\n'%i)
self.assertEqual(path.read_text(),'{"门":5}\n')
self.assertEqual(Path(str(path)+'.1').read_text(),'{"门":4}\n')
self.assertEqual(Path(str(path)+'.2').read_text(),'{"门":3}\n')
if __name__=='__main__':unittest.main()