test_config.py•5.26 kB
"""Tests for the configuration module."""
import os
import sys
from pathlib import Path
from arxiv_mcp_server.config import Settings
from unittest.mock import patch
@patch.object(Path, "mkdir")
@patch.object(Path, "resolve")
def test_storage_path_default(mock_resolve, mock_mkdir):
"""Test that the default storage path is correctly constructed."""
# Setup the mock to return the path itself when resolved
mock_resolve.side_effect = lambda: Path.home() / ".arxiv-mcp-server" / "papers"
settings = Settings()
expected_path = Path.home() / ".arxiv-mcp-server" / "papers"
assert settings.STORAGE_PATH == expected_path.resolve()
# Verify mkdir was called with parents=True and exist_ok=True
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
@patch.object(Path, "mkdir")
@patch.object(Path, "resolve")
def test_storage_path_from_args(mock_resolve, mock_mkdir):
"""Test that the storage path from command line args is correctly parsed."""
test_path = "/tmp/test_storage"
mock_resolve.side_effect = lambda: Path(test_path)
with patch.object(sys, "argv", ["program", "--storage-path", test_path]):
settings = Settings()
assert settings.STORAGE_PATH == Path(test_path).resolve()
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
@patch.object(Path, "mkdir")
@patch.object(Path, "resolve")
def test_storage_path_platform_compatibility(mock_resolve, mock_mkdir):
"""Test that the storage path works correctly on different platforms."""
# Test with a path format that would be valid on both Windows and Unix
test_paths = [
# Unix-style path
"/path/to/storage",
# Windows-style path
"C:\\path\\to\\storage",
# Path with spaces
"/path with spaces/to/storage",
# Path with non-ASCII characters
"/path/to/störâgè",
]
for test_path in test_paths:
# Reset mocks for each iteration
mock_resolve.reset_mock()
mock_mkdir.reset_mock()
# Set up the mock to return the path itself
mock_resolve.side_effect = lambda: Path(test_path)
with patch.object(sys, "argv", ["program", "--storage-path", test_path]):
settings = Settings()
resolved_path = settings.STORAGE_PATH
# Verify that Path constructor was called with the test path
assert resolved_path == Path(test_path).resolve()
# Verify that mkdir was called
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
def test_storage_path_creates_missing_directory():
"""Test that directories are actually created for the storage path."""
import tempfile
# Create a temporary directory for our test
with tempfile.TemporaryDirectory() as tmpdir:
# Create a path that doesn't exist yet
test_path = os.path.join(tmpdir, "deeply", "nested", "directory", "structure")
# Make sure it doesn't exist yet
assert not os.path.exists(test_path)
# Patch the arguments to use this path
with patch.object(sys, "argv", ["program", "--storage-path", test_path]):
# Access the STORAGE_PATH property which should create the directories
settings = Settings()
storage_path = settings.STORAGE_PATH
# Verify the directory was created
assert os.path.exists(test_path)
assert os.path.isdir(test_path)
# Verify the paths refer to the same location
# Use Path.samefile to handle symlinks (like /var -> /private/var on macOS)
assert Path(storage_path).samefile(test_path)
def test_path_normalization_with_windows_paths():
"""Test Windows-specific path handling using string operations only."""
# Windows-style paths - we'll test the normalization and joining logic
windows_style_paths = [
# Drive letter with backslashes
"C:\\Users\\username\\Documents\\Papers",
# UNC path (network share)
"\\\\server\\share\\papers",
# Drive letter with forward slashes (also valid on Windows)
"C:/Users/username/Documents/Papers",
# Windows-style path with spaces
"C:\\Program Files\\arXiv\\papers",
# Windows-style path with mixed slashes
"C:\\Users/username\\Documents/Papers",
]
# Test that our config works with these path formats
for windows_path in windows_style_paths:
assert Path(windows_path) # This should not raise an error
# Test path joining logic works correctly
subpath = Path(windows_path) / "subdir"
assert str(subpath).endswith("subdir")
# The following check is problematic on real Windows systems
# where the path separator may be different
# Check only that the base path is contained in the result (ignoring separator differences)
base_path_norm = windows_path.replace("\\", "/").replace("//", "/")
subpath_norm = str(subpath).replace("\\", "/").replace("//", "/")
assert base_path_norm in subpath_norm
# Instead of checking exact string equality, verify the Path objects are equivalent
assert subpath == Path(windows_path).joinpath("subdir")