EpisodeMatcher/test_episode_matching.py

186 lines
6.7 KiB
Python

#!/usr/bin/env python3
"""
Test script to verify episode matching logic with mock data.
"""
import sys
import os
from pathlib import Path
# Add src to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from Matcher.episode_renamer import EpisodeRenamer
def create_mock_episodes():
"""Create mock episode data to test the matching logic."""
return [
{
'path': Path('Disc 1_t01.mkv'),
'name': 'Disc 1_t01.mkv',
'size_bytes': 2 * 1024**3, # 2GB
'size_gb': 2.0,
'duration_minutes': 61.0,
},
{
'path': Path('Disc 1_t02.mkv'),
'name': 'Disc 1_t02.mkv',
'size_bytes': 2.1 * 1024**3, # 2.1GB
'size_gb': 2.1,
'duration_minutes': 55.0,
},
{
'path': Path('Disc 1_t03.mkv'),
'name': 'Disc 1_t03.mkv',
'size_bytes': 2.2 * 1024**3, # 2.2GB
'size_gb': 2.2,
'duration_minutes': 57.0,
},
{
'path': Path('Disc 2_t01.mkv'),
'name': 'Disc 2_t01.mkv',
'size_bytes': 2.0 * 1024**3, # 2GB
'size_gb': 2.0,
'duration_minutes': 55.0,
},
{
'path': Path('Disc 2_t02.mkv'),
'name': 'Disc 2_t02.mkv',
'size_bytes': 2.1 * 1024**3, # 2.1GB
'size_gb': 2.1,
'duration_minutes': 54.0,
},
{
'path': Path('Disc 2_t03.mkv'),
'name': 'Disc 2_t03.mkv',
'size_bytes': 1.9 * 1024**3, # 1.9GB
'size_gb': 1.9,
'duration_minutes': 52.0,
},
{
'path': Path('Disc 3_t01.mkv'),
'name': 'Disc 3_t01.mkv',
'size_bytes': 2.2 * 1024**3, # 2.2GB
'size_gb': 2.2,
'duration_minutes': 57.0,
},
{
'path': Path('Disc 3_t02.mkv'),
'name': 'Disc 3_t02.mkv',
'size_bytes': 2.1 * 1024**3, # 2.1GB
'size_gb': 2.1,
'duration_minutes': 58.0,
}
]
def create_mock_tvdb_episodes():
"""Create mock TVDB episode data."""
return [
{'episode_number': 1, 'name': 'Winter Is Coming', 'runtime': 61},
{'episode_number': 2, 'name': 'The Kingsroad', 'runtime': 55},
{'episode_number': 3, 'name': 'Lord Snow', 'runtime': 57},
{'episode_number': 4, 'name': 'Cripples, Bastards, and Broken Things', 'runtime': 55},
{'episode_number': 5, 'name': 'The Wolf and the Lion', 'runtime': 54},
{'episode_number': 6, 'name': 'A Golden Crown', 'runtime': 52},
{'episode_number': 7, 'name': 'You Win or You Die', 'runtime': 57},
{'episode_number': 8, 'name': 'The Pointy End', 'runtime': 58},
{'episode_number': 9, 'name': 'Baelor', 'runtime': 56},
{'episode_number': 10, 'name': 'Fire and Blood', 'runtime': 52},
]
def test_episode_matching():
"""Test the episode matching logic."""
print("=== Testing Episode Matching Logic ===\n")
# Create mock data
episodes = create_mock_episodes()
tvdb_episodes = create_mock_tvdb_episodes()
print(f"Mock episode files ({len(episodes)}):")
for ep in episodes:
print(f" - {ep['name']} ({ep['duration_minutes']} min)")
print(f"\nTVDB episodes ({len(tvdb_episodes)}):")
for ep in tvdb_episodes:
print(f" - Episode {ep['episode_number']}: {ep['name']} ({ep['runtime']} min)")
# Initialize renamer
renamer = EpisodeRenamer("/tmp/test", "Game of Thrones", 1)
# Test the matching logic
print("\n" + "="*80)
print("TESTING EPISODE MATCHING")
print("="*80)
try:
matched_episodes = renamer._match_episodes_by_duration(episodes, tvdb_episodes)
print(f"\n=== MATCHING RESULTS ===")
print(f"Successfully matched {len(matched_episodes)} episodes:")
for match in matched_episodes:
file_name = match['file_info']['path'].name
episode_num = match['episode_number']
tvdb_name = match['tvdb_info']['name'] if match['tvdb_info'] else 'Unknown'
duration_diff = match.get('duration_diff', 'N/A')
print(f" {file_name} → Episode {episode_num}: {tvdb_name}")
if duration_diff != 'N/A' and duration_diff is not None:
print(f" Duration difference: {duration_diff:.1f} minutes")
# Test validity of assignments
print(f"\n=== ASSIGNMENT VALIDATION ===")
episode_numbers = [m['episode_number'] for m in matched_episodes]
if len(set(episode_numbers)) == len(episode_numbers):
print("✓ All episodes assigned unique episode numbers")
else:
print("✗ Duplicate episode number assignments detected!")
duplicates = [x for x in episode_numbers if episode_numbers.count(x) > 1]
print(f" Duplicates: {set(duplicates)}")
# Check disc order constraint
disc_assignments = {}
for match in matched_episodes:
file_name = match['file_info']['path'].name
episode_num = match['episode_number']
# Extract disc number
if 'Disc 1' in file_name:
disc = 1
elif 'Disc 2' in file_name:
disc = 2
elif 'Disc 3' in file_name:
disc = 3
else:
disc = None
if disc:
if disc not in disc_assignments:
disc_assignments[disc] = []
disc_assignments[disc].append(episode_num)
print(f"\nDisc assignment validation:")
for disc in sorted(disc_assignments.keys()):
episodes = sorted(disc_assignments[disc])
print(f" Disc {disc}: Episodes {episodes}")
# Check if episodes are in reasonable order (earlier discs should have earlier episodes)
if disc == 1:
expected_range = list(range(1, 4)) # Episodes 1-3
elif disc == 2:
expected_range = list(range(4, 7)) # Episodes 4-6
elif disc == 3:
expected_range = list(range(7, 9)) # Episodes 7-8
if set(episodes).issubset(set(expected_range)):
print(f" ✓ Episodes {episodes} are within expected range {expected_range}")
else:
print(f" ⚠ Episodes {episodes} outside expected range {expected_range}")
except Exception as e:
print(f"Error during matching: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_episode_matching()