Files
romm/backend/tests/handler/filesystem/test_firmware_handler.py
2025-09-04 11:17:00 -03:00

214 lines
8.3 KiB
Python

import binascii
import hashlib
from pathlib import Path
from unittest.mock import patch
import pytest
from anyio import open_file
from config.config_manager import LIBRARY_BASE_PATH, Config
from exceptions.fs_exceptions import FirmwareNotFoundException
from handler.filesystem.firmware_handler import FSFirmwareHandler
from utils.hashing import crc32_to_hex
class TestFSFirmwareHandler:
"""Test suite for FSFirmwareHandler class"""
@pytest.fixture
def handler(self):
return FSFirmwareHandler()
@pytest.fixture
def config(self):
return Config(
EXCLUDED_PLATFORMS=[],
EXCLUDED_SINGLE_EXT=["tmp"],
EXCLUDED_SINGLE_FILES=[],
EXCLUDED_MULTI_FILES=[],
EXCLUDED_MULTI_PARTS_EXT=[],
EXCLUDED_MULTI_PARTS_FILES=[],
PLATFORMS_BINDING={},
PLATFORMS_VERSIONS={},
ROMS_FOLDER_NAME="roms",
FIRMWARE_FOLDER_NAME="bios",
)
def test_init_uses_library_base_path(self, handler: FSFirmwareHandler):
"""Test that FSFirmwareHandler initializes with LIBRARY_BASE_PATH"""
assert handler.base_path == Path(LIBRARY_BASE_PATH).resolve()
async def test_get_firmware(self, handler: FSFirmwareHandler, config):
"""Test get_firmware method"""
platform_fs_slug = "n64"
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
result = await handler.get_firmware(platform_fs_slug)
assert "bios1.bin" in result
assert "bios2.bin" in result
assert "temp.tmp" not in result
platform_fs_slug = "psx"
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
result = await handler.get_firmware(platform_fs_slug)
assert "scph1001.bin" in result
async def test_get_firmware_nonexistent_platform(
self, handler: FSFirmwareHandler, config
):
"""Test get_firmware method with nonexistent platform"""
platform_fs_slug = "nonexistent"
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
with pytest.raises(FirmwareNotFoundException):
await handler.get_firmware(platform_fs_slug)
async def test_calculate_file_hashes(self, handler: FSFirmwareHandler):
"""Test calculate_file_hashes method with actual file"""
firmware_path = "n64/bios"
file_name = "bios1.bin"
result = await handler.calculate_file_hashes(firmware_path, file_name)
assert isinstance(result, dict)
assert "crc_hash" in result
assert "md5_hash" in result
assert "sha1_hash" in result
assert isinstance(result["crc_hash"], str)
assert isinstance(result["md5_hash"], str)
assert isinstance(result["sha1_hash"], str)
assert len(result["crc_hash"]) > 0
assert len(result["md5_hash"]) > 0
assert len(result["sha1_hash"]) > 0
file_path = handler.base_path / firmware_path / file_name
async with await open_file(file_path, "rb") as f:
content = await f.read()
crc_expected = crc32_to_hex(binascii.crc32(content))
md5_expected = hashlib.md5(content, usedforsecurity=False).hexdigest()
sha1_expected = hashlib.sha1(content, usedforsecurity=False).hexdigest()
result = await handler.calculate_file_hashes(firmware_path, file_name)
assert result["crc_hash"] == crc_expected
assert result["md5_hash"] == md5_expected
assert result["sha1_hash"] == sha1_expected
async def test_calculate_file_hashes_different_files(
self, handler: FSFirmwareHandler
):
"""Test calculate_file_hashes with different files have different hashes"""
firmware_path = "n64/bios"
result1 = await handler.calculate_file_hashes(firmware_path, "bios1.bin")
result2 = await handler.calculate_file_hashes(firmware_path, "bios2.bin")
# Different files should have different hashes
assert result1["crc_hash"] != result2["crc_hash"]
assert result1["md5_hash"] != result2["md5_hash"]
assert result1["sha1_hash"] != result2["sha1_hash"]
async def test_calculate_file_hashes_nonexistent_file(
self, handler: FSFirmwareHandler
):
"""Test calculate_file_hashes with nonexistent file"""
firmware_path = "n64/bios"
file_name = "nonexistent.bin"
with pytest.raises(FileNotFoundError):
await handler.calculate_file_hashes(firmware_path, file_name)
def test_integration_with_base_handler_methods(self, handler: FSFirmwareHandler):
"""Test that FSFirmwareHandler properly inherits from FSHandler"""
# Test that handler has base methods
assert hasattr(handler, "validate_path")
assert hasattr(handler, "list_files")
assert hasattr(handler, "file_exists")
assert hasattr(handler, "move_file_or_folder")
assert hasattr(handler, "stream_file")
assert hasattr(handler, "exclude_single_files")
def test_firmware_path_construction(self, handler: FSFirmwareHandler, config):
"""Test that firmware paths are constructed correctly"""
platform_fs_slug = "n64"
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
# Test normal path (high prio doesn't exist)
path = handler.get_firmware_fs_structure(platform_fs_slug)
assert path == f"{platform_fs_slug}/{config.FIRMWARE_FOLDER_NAME}"
async def test_multiple_platform_handling(self, handler: FSFirmwareHandler, config):
"""Test handling of different platform slugs"""
platforms = ["n64", "psx"] # Use platforms that actually exist in test data
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
for platform in platforms:
path = handler.get_firmware_fs_structure(platform)
assert platform in path
assert config.FIRMWARE_FOLDER_NAME in path
# Test that we can actually get firmware for existing platforms
firmware_files = await handler.get_firmware(platform)
assert len(firmware_files) > 0 # Should have at least one file
async def test_exclude_single_files_integration(
self, handler: FSFirmwareHandler, config
):
"""Test that exclude_single_files works with actual files"""
platform_fs_slug = "n64"
with patch(
"handler.filesystem.firmware_handler.cm.get_config", return_value=config
):
# Get all files in the directory
firmware_path = handler.get_firmware_fs_structure(platform_fs_slug)
all_files = await handler.list_files(path=firmware_path)
# Should include .tmp files before exclusion
assert "temp.tmp" in all_files
assert "bios1.bin" in all_files
assert "bios2.bin" in all_files
# After exclusion, .tmp files should be removed
filtered_files = handler.exclude_single_files(all_files)
assert "temp.tmp" not in filtered_files
assert "bios1.bin" in filtered_files
assert "bios2.bin" in filtered_files
async def test_file_operations_with_actual_structure(
self, handler: FSFirmwareHandler
):
"""Test that file operations work with the actual directory structure"""
# Test that we can list files
n64_files = await handler.list_files("n64/bios")
assert len(n64_files) > 0
psx_files = await handler.list_files("psx/bios")
assert len(psx_files) > 0
# Test that we can check file existence
assert await handler.file_exists("n64/bios/bios1.bin")
assert await handler.file_exists("psx/bios/scph1001.bin")
assert not await handler.file_exists("n64/bios/nonexistent.bin")
async def test_stream_file_with_actual_files(self, handler: FSFirmwareHandler):
"""Test streaming actual files"""
async with await handler.stream_file("n64/bios/bios1.bin") as f:
content = await f.read()
assert len(content) > 0
assert b"This is a test N64 BIOS file 1" in content