Files
romm/backend/tests/handler/filesystem/test_platforms_handler.py
Georges-Antoine Assi 661a5504d7 find a couple more uses
2026-02-09 17:26:21 -05:00

396 lines
16 KiB
Python

from pathlib import Path
from unittest.mock import patch
import pytest
from config.config_manager import LIBRARY_BASE_PATH, Config
from handler.filesystem.platforms_handler import FSPlatformsHandler, LibraryStructure
class TestFSPlatformsHandler:
"""Test suite for FSPlatformsHandler class"""
@pytest.fixture
def handler(self):
return FSPlatformsHandler()
@pytest.fixture
def config(self):
return Config(
EXCLUDED_PLATFORMS=["romm", "excluded_platform"],
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",
)
@pytest.fixture
def config_custom_folder(self):
return Config(
EXCLUDED_PLATFORMS=[],
EXCLUDED_SINGLE_EXT=[],
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: FSPlatformsHandler):
"""Test that FSPlatformsHandler initializes with LIBRARY_BASE_PATH"""
assert handler.base_path == Path(LIBRARY_BASE_PATH).resolve()
def test_exclude_platforms_filters_excluded_platforms(
self, handler: FSPlatformsHandler, config
):
"""Test that _exclude_platforms filters out excluded platforms"""
platforms = ["n64", "psx", "romm", "excluded_platform", "gba"]
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = handler._exclude_platforms(platforms)
assert "n64" in result
assert "psx" in result
assert "gba" in result
assert "romm" not in result
assert "excluded_platform" not in result
def test_exclude_platforms_empty_list(self, handler: FSPlatformsHandler, config):
"""Test that _exclude_platforms handles empty list"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = handler._exclude_platforms([])
assert result == []
def test_exclude_platforms_no_excluded_config(
self, handler: FSPlatformsHandler, config_custom_folder
):
"""Test that _exclude_platforms works when no platforms are excluded"""
platforms = ["n64", "psx", "gba"]
with patch(
"handler.filesystem.platforms_handler.cm.get_config",
return_value=config_custom_folder,
):
result = handler._exclude_platforms(platforms)
assert result == platforms
def test_get_platforms_directory_high_priority_structure(
self, handler: FSPlatformsHandler, config
):
"""Test get_platforms_directory with high priority structure"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=True):
result = handler.get_platforms_directory()
assert result == config.ROMS_FOLDER_NAME
def test_get_platforms_directory_normal_structure(
self, handler: FSPlatformsHandler, config
):
"""Test get_platforms_directory with normal structure"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=False):
result = handler.get_platforms_directory()
assert result == ""
def test_get_platform_fs_structure_high_priority(
self, handler: FSPlatformsHandler, config
):
"""Test get_platform_fs_structure with high priority structure"""
fs_slug = "n64"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=True):
result = handler.get_platform_fs_structure(fs_slug)
assert result == f"{config.ROMS_FOLDER_NAME}/{fs_slug}"
def test_get_platform_fs_structure_normal_structure(
self, handler: FSPlatformsHandler, config
):
"""Test get_platform_fs_structure with normal structure"""
fs_slug = "n64"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = handler.get_platform_fs_structure(fs_slug)
assert result == f"{fs_slug}/{config.ROMS_FOLDER_NAME}"
def test_get_platform_fs_structure_custom_folder_name(
self, handler: FSPlatformsHandler, config_custom_folder
):
"""Test get_platform_fs_structure with custom folder name"""
fs_slug = "psx"
with patch(
"handler.filesystem.platforms_handler.cm.get_config",
return_value=config_custom_folder,
):
result = handler.get_platform_fs_structure(fs_slug)
assert result == f"{fs_slug}/{config_custom_folder.ROMS_FOLDER_NAME}"
async def test_add_platform_creates_directory(
self, handler: FSPlatformsHandler, config
):
"""Test that add_platform creates the correct directory"""
fs_slug = "gba"
expected_path = f"{config.ROMS_FOLDER_NAME}/{fs_slug}"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=True):
with patch.object(handler, "make_directory") as mock_make_directory:
await handler.add_platform(fs_slug)
mock_make_directory.assert_called_once_with(expected_path)
async def test_add_platform_normal_structure(
self, handler: FSPlatformsHandler, config
):
"""Test that add_platform creates directory with normal structure"""
fs_slug = "gba"
expected_path = f"{fs_slug}/{config.ROMS_FOLDER_NAME}"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=False):
with patch.object(handler, "make_directory") as mock_make_directory:
await handler.add_platform(fs_slug)
mock_make_directory.assert_called_once_with(expected_path)
async def test_get_platforms_returns_existing_platforms(
self, handler: FSPlatformsHandler, config
):
"""Test that get_platforms returns existing platforms"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = await handler.get_platforms()
assert "n64" in result
assert "psx" in result
async def test_get_platforms_excludes_excluded_platforms(
self, handler: FSPlatformsHandler, config
):
"""Test that get_platforms excludes excluded platforms"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
config.EXCLUDED_PLATFORMS = ["psx"]
result = await handler.get_platforms()
assert "n64" in result
assert "psx" not in result
async def test_get_platforms_calls_list_directories_with_correct_path(
self, handler: FSPlatformsHandler, config
):
"""Test that get_platforms calls list_directories with correct path"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=True):
with patch.object(
handler, "list_directories", return_value=[]
) as mock_list:
await handler.get_platforms()
mock_list.assert_called_once_with(path=config.ROMS_FOLDER_NAME)
async def test_get_platforms_calls_list_directories_with_empty_path(
self, handler: FSPlatformsHandler, config
):
"""Test that get_platforms calls list_directories with empty path for normal structure"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch.object(
handler, "list_directories", return_value=[]
) as mock_list:
await handler.get_platforms()
mock_list.assert_called_once_with(path="")
def test_integration_with_base_handler_methods(self, handler: FSPlatformsHandler):
"""Test that FSPlatformsHandler properly inherits from FSHandler"""
# Test that handler has base methods
assert hasattr(handler, "validate_path")
assert hasattr(handler, "list_directories")
assert hasattr(handler, "make_directory")
assert hasattr(handler, "file_exists")
assert hasattr(handler, "move_file_or_folder")
assert hasattr(handler, "stream_file")
def test_platform_slug_handling_with_special_characters(
self, handler: FSPlatformsHandler, config
):
"""Test that platform slugs with special characters are handled correctly"""
fs_slug = "n64"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = handler.get_platform_fs_structure(fs_slug)
assert result == f"{fs_slug}/{config.ROMS_FOLDER_NAME}"
async def test_path_construction_consistency(
self, handler: FSPlatformsHandler, config
):
"""Test that path construction is consistent across methods"""
fs_slug = "ps2"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
# Test both methods return consistent paths
structure_path = handler.get_platform_fs_structure(fs_slug)
with patch.object(handler, "make_directory") as mock_make_directory:
await handler.add_platform(fs_slug)
mock_make_directory.assert_called_once_with(structure_path)
def test_actual_directory_operations(self, handler: FSPlatformsHandler, config):
"""Test operations with actual directory structure"""
# Test with existing platforms
existing_platforms = ["n64", "psx"]
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
for platform in existing_platforms:
expected_path = f"{platform}/{config.ROMS_FOLDER_NAME}"
result = handler.get_platform_fs_structure(platform)
assert result == expected_path
async def test_edge_cases_and_error_handling(
self, handler: FSPlatformsHandler, config
):
"""Test edge cases and error handling"""
# Test with empty platform slug
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
result = handler.get_platform_fs_structure("")
assert result == f"/{config.ROMS_FOLDER_NAME}"
# Test adding empty platform
with patch.object(handler, "make_directory") as mock_make_directory:
await handler.add_platform("")
mock_make_directory.assert_called_once_with(
f"/{config.ROMS_FOLDER_NAME}"
)
def test_multiple_platforms_handling(self, handler: FSPlatformsHandler, config):
"""Test handling multiple platforms simultaneously"""
platforms = ["n64", "psx", "gba", "romm", "excluded_platform"]
expected_filtered = ["n64", "psx", "gba"]
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
filtered = handler._exclude_platforms(platforms)
assert set(filtered) == set(expected_filtered)
# Test that each platform gets correct structure
for platform in expected_filtered:
structure = handler.get_platform_fs_structure(platform)
assert structure == f"{platform}/{config.ROMS_FOLDER_NAME}"
def test_detect_library_structure_structure_a(
self, handler: FSPlatformsHandler, config
):
"""Test detect_library_structure detects Structure A (roms/{platform})"""
roms_path = f"{LIBRARY_BASE_PATH}/{config.ROMS_FOLDER_NAME}"
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists") as mock_exists:
mock_exists.return_value = True
result = handler.detect_library_structure()
assert result == LibraryStructure.A
mock_exists.assert_called_once_with(roms_path)
def test_detect_library_structure_structure_b(
self, handler: FSPlatformsHandler, config
):
"""Test detect_library_structure detects Structure B ({platform}/roms)"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists") as mock_exists:
# ROMs folder doesn't exist at base level
mock_exists.return_value = False
with patch("os.listdir") as mock_listdir:
mock_listdir.return_value = ["n64", "psx", "other_folder"]
with patch("os.path.isdir") as mock_isdir:
# n64 and psx are directories with roms subfolders
def isdir_side_effect(path):
return "n64" in path or "psx" in path
def exists_side_effect(path):
# n64/roms and psx/roms exist
return (
f"n64/{config.ROMS_FOLDER_NAME}" in path
or f"psx/{config.ROMS_FOLDER_NAME}" in path
)
mock_isdir.side_effect = isdir_side_effect
mock_exists.side_effect = exists_side_effect
result = handler.detect_library_structure()
assert result == LibraryStructure.B
def test_detect_library_structure_none(self, handler: FSPlatformsHandler, config):
"""Test detect_library_structure returns None when no structure detected"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=False):
with patch("os.listdir", return_value=[]):
result = handler.detect_library_structure()
assert result is None
def test_detect_library_structure_handles_os_errors(
self, handler: FSPlatformsHandler, config
):
"""Test detect_library_structure handles OS errors gracefully"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=False):
with patch("os.listdir", side_effect=OSError("Permission denied")):
result = handler.detect_library_structure()
assert result is None
def test_detect_library_structure_empty_library(
self, handler: FSPlatformsHandler, config
):
"""Test detect_library_structure with empty library directory"""
with patch(
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
):
with patch("os.path.exists", return_value=False):
with patch("os.listdir", return_value=[]):
result = handler.detect_library_structure()
assert result is None