mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-22 13:42:12 -03:00
- Add cache entry validator service for data integrity checks - Add cache health monitor service for periodic health checks - Enhance model cache and scanner with validation support - Update websocket manager for health status broadcasting - Add initialization banner service for cache health alerts - Add comprehensive test coverage for new services - Update translations across all locales - Refactor sync translation keys script
168 lines
5.4 KiB
Python
168 lines
5.4 KiB
Python
"""
|
|
Integration tests for cache validation in ModelScanner
|
|
"""
|
|
|
|
import pytest
|
|
import asyncio
|
|
|
|
from py.services.model_scanner import ModelScanner
|
|
from py.services.cache_entry_validator import CacheEntryValidator
|
|
from py.services.cache_health_monitor import CacheHealthMonitor, CacheHealthStatus
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_model_scanner_validates_cache_entries(tmp_path_factory):
|
|
"""Test that ModelScanner validates cache entries during initialization"""
|
|
# Create temporary test data
|
|
tmp_dir = tmp_path_factory.mktemp("test_loras")
|
|
|
|
# Create test files
|
|
test_file = tmp_dir / "test_model.safetensors"
|
|
test_file.write_bytes(b"fake model data" * 100)
|
|
|
|
# Mock model scanner (we can't easily instantiate a full scanner in tests)
|
|
# Instead, test the validation logic directly
|
|
entries = [
|
|
{
|
|
'file_path': str(test_file),
|
|
'sha256': 'abc123def456',
|
|
'file_name': 'test_model.safetensors',
|
|
},
|
|
{
|
|
'file_path': str(tmp_dir / 'invalid.safetensors'),
|
|
# Missing sha256 - invalid
|
|
},
|
|
]
|
|
|
|
valid, invalid = CacheEntryValidator.validate_batch(entries, auto_repair=True)
|
|
|
|
assert len(valid) == 1
|
|
assert len(invalid) == 1
|
|
assert valid[0]['sha256'] == 'abc123def456'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_model_scanner_detects_degraded_cache():
|
|
"""Test that ModelScanner detects degraded cache health"""
|
|
# Create 100 entries with 2% corruption
|
|
entries = [
|
|
{
|
|
'file_path': f'/models/test{i}.safetensors',
|
|
'sha256': f'hash{i}',
|
|
}
|
|
for i in range(98)
|
|
]
|
|
# Add 2 invalid entries
|
|
entries.append({'file_path': '/models/invalid1.safetensors'})
|
|
entries.append({'file_path': '/models/invalid2.safetensors'})
|
|
|
|
monitor = CacheHealthMonitor()
|
|
report = monitor.check_health(entries, auto_repair=True)
|
|
|
|
assert report.status == CacheHealthStatus.DEGRADED
|
|
assert report.invalid_entries == 2
|
|
assert report.valid_entries == 98
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_model_scanner_detects_corrupted_cache():
|
|
"""Test that ModelScanner detects corrupted cache health"""
|
|
# Create 100 entries with 10% corruption
|
|
entries = [
|
|
{
|
|
'file_path': f'/models/test{i}.safetensors',
|
|
'sha256': f'hash{i}',
|
|
}
|
|
for i in range(90)
|
|
]
|
|
# Add 10 invalid entries
|
|
for i in range(10):
|
|
entries.append({'file_path': f'/models/invalid{i}.safetensors'})
|
|
|
|
monitor = CacheHealthMonitor()
|
|
report = monitor.check_health(entries, auto_repair=True)
|
|
|
|
assert report.status == CacheHealthStatus.CORRUPTED
|
|
assert report.invalid_entries == 10
|
|
assert report.valid_entries == 90
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_model_scanner_removes_invalid_from_hash_index():
|
|
"""Test that ModelScanner removes invalid entries from hash index"""
|
|
from py.services.model_hash_index import ModelHashIndex
|
|
|
|
# Create a hash index with some entries
|
|
hash_index = ModelHashIndex()
|
|
valid_entry = {
|
|
'file_path': '/models/valid.safetensors',
|
|
'sha256': 'abc123',
|
|
}
|
|
invalid_entry = {
|
|
'file_path': '/models/invalid.safetensors',
|
|
'sha256': '', # Empty sha256
|
|
}
|
|
|
|
# Add entries to hash index
|
|
hash_index.add_entry(valid_entry['sha256'], valid_entry['file_path'])
|
|
hash_index.add_entry(invalid_entry['sha256'], invalid_entry['file_path'])
|
|
|
|
# Verify both entries are in the index (using get_hash method)
|
|
assert hash_index.get_hash(valid_entry['file_path']) == valid_entry['sha256']
|
|
# Invalid entry won't be added due to empty sha256
|
|
assert hash_index.get_hash(invalid_entry['file_path']) is None
|
|
|
|
# Simulate removing invalid entry (it's not actually there, but let's test the method)
|
|
hash_index.remove_by_path(
|
|
CacheEntryValidator.get_file_path_safe(invalid_entry),
|
|
CacheEntryValidator.get_sha256_safe(invalid_entry)
|
|
)
|
|
|
|
# Verify valid entry remains
|
|
assert hash_index.get_hash(valid_entry['file_path']) == valid_entry['sha256']
|
|
|
|
|
|
def test_cache_entry_validator_handles_various_field_types():
|
|
"""Test that validator handles various field types correctly"""
|
|
# Test with different field types
|
|
entry = {
|
|
'file_path': '/models/test.safetensors',
|
|
'sha256': 'abc123',
|
|
'size': 1024, # int
|
|
'modified': 1234567890.0, # float
|
|
'favorite': True, # bool
|
|
'tags': ['tag1', 'tag2'], # list
|
|
'exclude': False, # bool
|
|
}
|
|
|
|
result = CacheEntryValidator.validate(entry, auto_repair=False)
|
|
|
|
assert result.is_valid is True
|
|
assert result.repaired is False
|
|
|
|
|
|
def test_cache_health_report_serialization():
|
|
"""Test that HealthReport can be serialized to dict"""
|
|
from py.services.cache_health_monitor import HealthReport
|
|
|
|
report = HealthReport(
|
|
status=CacheHealthStatus.DEGRADED,
|
|
total_entries=100,
|
|
valid_entries=98,
|
|
invalid_entries=2,
|
|
repaired_entries=1,
|
|
invalid_paths=['/path1', '/path2'],
|
|
message="Cache issues detected"
|
|
)
|
|
|
|
result = report.to_dict()
|
|
|
|
assert result['status'] == 'degraded'
|
|
assert result['total_entries'] == 100
|
|
assert result['valid_entries'] == 98
|
|
assert result['invalid_entries'] == 2
|
|
assert result['repaired_entries'] == 1
|
|
assert result['corruption_rate'] == '2.0%'
|
|
assert len(result['invalid_paths']) == 2
|
|
assert result['message'] == "Cache issues detected"
|