import json from fam_edge.oracle_db import OracleDB from fam_edge.person_service import PersonService def _service(tmp_path): db = OracleDB(str(tmp_path / "oracle.db")) svc = PersonService.__new__(PersonService) # 跳过 __init__(不需要真的建 LLM 适配器) svc.db = db return svc, db def _insert_event(db, video_id, appearances): db._conn.execute( "INSERT INTO events (video_id, ts, description, person_appearances_json) " "VALUES (?, ?, ?, ?)", (video_id, "2026-08-21 00:00:00", "desc", json.dumps(appearances, ensure_ascii=False))) db._conn.commit() def test_aggregate_features_merges_same_gender_across_videos(tmp_path): svc, db = _service(tmp_path) _insert_event(db, 1, [{"uid": "人物A", "features": {"gender": "男", "hair": "短发黑色"}}]) _insert_event(db, 2, [{"uid": "人物A", "features": {"gender": "男", "clothing": "蓝色T恤"}}]) result = svc._aggregate_features() assert set(result.keys()) == {"人物A"} assert result["人物A"]["hair"] == "短发黑色" assert result["人物A"]["clothing"] == "蓝色T恤" def test_aggregate_features_splits_gender_conflict_across_videos(tmp_path): """核心场景: 复现 "人物A" 在 29 个视频里混了男女两个人的真实 bug——不同视频各自 独立编号的 uid,字符串相同不代表同一个真人,性别冲突时必须拆成独立分组。""" svc, db = _service(tmp_path) _insert_event(db, 1, [{"uid": "人物A", "features": {"gender": "男", "clothing": "蓝色Polo衫"}}]) _insert_event(db, 2, [{"uid": "人物A", "features": {"gender": "女", "clothing": "白色上衣"}}]) result = svc._aggregate_features() assert set(result.keys()) == {"人物A", "人物A#2"} assert result["人物A"]["gender"] == "男" assert result["人物A#2"]["gender"] == "女" def test_aggregate_features_unknown_gender_joins_first_group(tmp_path): svc, db = _service(tmp_path) _insert_event(db, 1, [{"uid": "人物A", "features": {"gender": "男"}}]) _insert_event(db, 2, [{"uid": "人物A", "features": {"gender": "unknown", "hair": "光头"}}]) result = svc._aggregate_features() assert set(result.keys()) == {"人物A"} assert result["人物A"]["gender"] == "男" assert result["人物A"]["hair"] == "光头" def test_aggregate_features_three_way_gender_reuse_creates_three_groups(tmp_path): svc, db = _service(tmp_path) _insert_event(db, 1, [{"uid": "人物B", "features": {"gender": "男"}}]) _insert_event(db, 2, [{"uid": "人物B", "features": {"gender": "女"}}]) _insert_event(db, 3, [{"uid": "人物B", "features": {"gender": "男"}}]) # 应并回第一组 result = svc._aggregate_features() assert set(result.keys()) == {"人物B", "人物B#2"} assert result["人物B"]["gender"] == "男" assert result["人物B#2"]["gender"] == "女" def test_aggregate_features_ignores_placeholder_uids(tmp_path): svc, db = _service(tmp_path) _insert_event(db, 1, [{"uid": "无人", "features": {"gender": "男"}}]) _insert_event(db, 2, [{"uid": "", "features": {"gender": "男"}}]) result = svc._aggregate_features() assert result == {}