refactor review-plan safety and validation
This commit is contained in:
@@ -614,6 +614,114 @@ def test_generate_plan_with_analysis_by_reputation_missing_scores_uses_fallback_
|
||||
assert "评分依据不足" in plan.human_summary
|
||||
|
||||
|
||||
|
||||
|
||||
def test_generate_plan_with_analysis_by_quality_missing_quality_data_marks_manual_review(config):
|
||||
"""Missing quality entries should not silently keep the first duplicate."""
|
||||
config.duplicate_keep = "by_quality"
|
||||
p_low = Path("/mnt/nas/videos/movie/Test.2020.720p.WEB-DL.mkv")
|
||||
p_high = Path("/mnt/nas/videos/movie/Test.2020.1080p.BluRay.mkv")
|
||||
vf_low = VideoFile(
|
||||
path=p_low,
|
||||
filename="Test.2020.720p.WEB-DL.mkv",
|
||||
size_bytes=1000000,
|
||||
modified_timestamp=datetime.now(timezone.utc),
|
||||
category="movie",
|
||||
)
|
||||
vf_high = VideoFile(
|
||||
path=p_high,
|
||||
filename="Test.2020.1080p.BluRay.mkv",
|
||||
size_bytes=2000000,
|
||||
modified_timestamp=datetime.now(timezone.utc),
|
||||
category="movie",
|
||||
)
|
||||
identity = MovieIdentity(
|
||||
title="Test",
|
||||
year=2020,
|
||||
confidence=0.9,
|
||||
needs_review=False,
|
||||
original_filename="Test.2020.mkv",
|
||||
)
|
||||
|
||||
plan = generate_plan(
|
||||
[(vf_low, identity), (vf_high, identity)],
|
||||
config,
|
||||
analysis_data={
|
||||
"metadata": {"source_identities": "identities.json"},
|
||||
"completeness": [],
|
||||
"duplicates": [
|
||||
{
|
||||
"identity": {"type": "movie", "title": "Test", "year": 2020},
|
||||
"files": [str(p_low), str(p_high)],
|
||||
"quality_comparison": [
|
||||
{"path": str(p_low), "resolution": "1280x720", "size_bytes": 1000000},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert all(op.operation_type == "no-op" for op in plan.operations)
|
||||
assert "Duplicate group needs manual review" in plan.operations[0].reason
|
||||
issues = plan.metadata["validation_snapshot"]["duplicate_resolution_issues"]
|
||||
assert len(issues) == 1
|
||||
assert "missing quality comparison entries" in issues[0]["reason"]
|
||||
assert "转人工复核" in plan.human_summary
|
||||
|
||||
|
||||
def test_generate_plan_normalizes_duplicate_paths_before_matching(config):
|
||||
"""Duplicate matching should survive harmless path-format differences."""
|
||||
config.duplicate_keep = "by_quality"
|
||||
p_720 = Path("/mnt/nas/videos/movie/Test.2020.720p.WEB-DL.mkv")
|
||||
p_1080 = Path("/mnt/nas/videos/movie/Test.2020.1080p.BluRay.mkv")
|
||||
vf_720 = VideoFile(
|
||||
path=p_720,
|
||||
filename="Test.2020.720p.WEB-DL.mkv",
|
||||
size_bytes=1000000,
|
||||
modified_timestamp=datetime.now(timezone.utc),
|
||||
category="movie",
|
||||
)
|
||||
vf_1080 = VideoFile(
|
||||
path=p_1080,
|
||||
filename="Test.2020.1080p.BluRay.mkv",
|
||||
size_bytes=2000000,
|
||||
modified_timestamp=datetime.now(timezone.utc),
|
||||
category="movie",
|
||||
)
|
||||
identity = MovieIdentity(
|
||||
title="Test",
|
||||
year=2020,
|
||||
confidence=0.9,
|
||||
needs_review=False,
|
||||
original_filename="Test.2020.mkv",
|
||||
)
|
||||
|
||||
normalized_low = str(p_720.parent / "." / p_720.name)
|
||||
normalized_high = str(p_1080.parent / "." / p_1080.name)
|
||||
plan = generate_plan(
|
||||
[(vf_720, identity), (vf_1080, identity)],
|
||||
config,
|
||||
analysis_data={
|
||||
"metadata": {"source_identities": "identities.json"},
|
||||
"completeness": [],
|
||||
"duplicates": [
|
||||
{
|
||||
"identity": {"type": "movie", "title": "Test", "year": 2020},
|
||||
"files": [normalized_low, normalized_high],
|
||||
"quality_comparison": [
|
||||
{"path": normalized_low, "resolution": "1280x720", "size_bytes": 1000000},
|
||||
{"path": normalized_high, "resolution": "1920x1080", "size_bytes": 2000000},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert plan.summary["quarantine"] == 1
|
||||
assert plan.operations[0].operation_type == "quarantine"
|
||||
assert plan.operations[1].operation_type == "move"
|
||||
|
||||
|
||||
def test_generate_plan_human_summary_marks_disc_files_as_high_risk(config):
|
||||
"""Disc/part files should be listed with a conservative risk note in summary."""
|
||||
config.duplicate_keep = "by_reputation"
|
||||
|
||||
Reference in New Issue
Block a user