test: reorganize core suite into explicit domain files
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from auditui.constants import MIN_FILE_SIZE
|
||||
from auditui.downloads import DownloadManager
|
||||
|
||||
|
||||
def _manager_with_cache_dir(tmp_path: Path) -> DownloadManager:
|
||||
"""Build a lightweight DownloadManager instance without real HTTP clients."""
|
||||
manager = DownloadManager.__new__(DownloadManager)
|
||||
manager.cache_dir = tmp_path
|
||||
manager.chunk_size = 1024
|
||||
return manager
|
||||
|
||||
|
||||
def test_sanitize_filename_replaces_invalid_characters() -> None:
|
||||
"""Ensure filesystem-invalid symbols are replaced with underscores."""
|
||||
manager = DownloadManager.__new__(DownloadManager)
|
||||
assert manager._sanitize_filename('a<>:"/\\|?*b') == "a_________b"
|
||||
|
||||
|
||||
def test_validate_download_url_accepts_only_http_schemes() -> None:
|
||||
"""Ensure download URL validation only accepts HTTP and HTTPS links."""
|
||||
manager = DownloadManager.__new__(DownloadManager)
|
||||
assert manager._validate_download_url("https://example.com/file") is True
|
||||
assert manager._validate_download_url("http://example.com/file") is True
|
||||
assert manager._validate_download_url("ftp://example.com/file") is False
|
||||
|
||||
|
||||
def test_get_cached_path_and_remove_cached(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Ensure cache lookup and cache deletion work for valid files."""
|
||||
manager = _manager_with_cache_dir(tmp_path)
|
||||
monkeypatch.setattr(manager, "_get_name_from_asin", lambda asin: "My Book")
|
||||
cached_path = tmp_path / "My Book.aax"
|
||||
cached_path.write_bytes(b"0" * MIN_FILE_SIZE)
|
||||
messages: list[str] = []
|
||||
assert manager.get_cached_path("ASIN123") == cached_path
|
||||
assert manager.is_cached("ASIN123") is True
|
||||
assert manager.remove_cached("ASIN123", notify=messages.append) is True
|
||||
assert not cached_path.exists()
|
||||
assert "Removed from cache" in messages[-1]
|
||||
|
||||
|
||||
def test_get_cached_path_ignores_small_files(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Ensure undersized files are not treated as valid cache entries."""
|
||||
manager = _manager_with_cache_dir(tmp_path)
|
||||
monkeypatch.setattr(manager, "_get_name_from_asin", lambda asin: "My Book")
|
||||
cached_path = tmp_path / "My Book.aax"
|
||||
cached_path.write_bytes(b"0" * (MIN_FILE_SIZE - 1))
|
||||
assert manager.get_cached_path("ASIN123") is None
|
||||
85
tests/downloads/test_download_manager_workflow.py
Normal file
85
tests/downloads/test_download_manager_workflow.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from auditui.constants import MIN_FILE_SIZE
|
||||
from auditui.downloads import DownloadManager
|
||||
from auditui.downloads import manager as manager_mod
|
||||
|
||||
|
||||
def _bare_manager(tmp_path: Path) -> DownloadManager:
|
||||
"""Create manager without invoking constructor side effects."""
|
||||
manager = DownloadManager.__new__(DownloadManager)
|
||||
manager.cache_dir = tmp_path
|
||||
manager.chunk_size = 1024
|
||||
manager.auth = type(
|
||||
"Auth", (), {"adp_token": "x", "locale": type("Loc", (), {"domain": "fr"})()}
|
||||
)()
|
||||
return manager
|
||||
|
||||
|
||||
def test_get_activation_bytes_returns_hex(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
"""Ensure activation bytes are converted to lowercase hex string."""
|
||||
manager = _bare_manager(tmp_path)
|
||||
monkeypatch.setattr(manager_mod, "get_activation_bytes", lambda _auth: b"\xde\xad")
|
||||
assert manager.get_activation_bytes() == "dead"
|
||||
|
||||
|
||||
def test_get_activation_bytes_handles_errors(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
"""Ensure activation retrieval failures are handled gracefully."""
|
||||
manager = _bare_manager(tmp_path)
|
||||
|
||||
def _boom(_auth: object) -> bytes:
|
||||
"""Raise a deterministic failure for exception-path coverage."""
|
||||
raise OSError("no auth")
|
||||
|
||||
monkeypatch.setattr(manager_mod, "get_activation_bytes", _boom)
|
||||
assert manager.get_activation_bytes() is None
|
||||
|
||||
|
||||
def test_get_or_download_uses_cached_file_when_available(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Ensure cached files bypass link generation and download work."""
|
||||
manager = _bare_manager(tmp_path)
|
||||
monkeypatch.setattr(manager, "_get_name_from_asin", lambda asin: "Book")
|
||||
cached_path = tmp_path / "Book.aax"
|
||||
cached_path.write_bytes(b"1" * MIN_FILE_SIZE)
|
||||
messages: list[str] = []
|
||||
assert manager.get_or_download("ASIN", notify=messages.append) == cached_path
|
||||
assert "Using cached file" in messages[0]
|
||||
|
||||
|
||||
def test_get_or_download_reports_invalid_url(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Ensure workflow reports invalid download URLs and aborts."""
|
||||
manager = _bare_manager(tmp_path)
|
||||
monkeypatch.setattr(manager, "_get_name_from_asin", lambda asin: "Book")
|
||||
monkeypatch.setattr(
|
||||
manager, "_get_download_link", lambda asin, notify=None: "ftp://bad"
|
||||
)
|
||||
messages: list[str] = []
|
||||
assert manager.get_or_download("ASIN", notify=messages.append) is None
|
||||
assert "Invalid download URL" in messages
|
||||
|
||||
|
||||
def test_get_or_download_handles_download_failure(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Ensure workflow reports failures when stream download does not complete."""
|
||||
manager = _bare_manager(tmp_path)
|
||||
monkeypatch.setattr(manager, "_get_name_from_asin", lambda asin: "Book")
|
||||
monkeypatch.setattr(
|
||||
manager, "_get_download_link", lambda asin, notify=None: "https://ok"
|
||||
)
|
||||
monkeypatch.setattr(manager, "_download_file", lambda url, path, notify=None: None)
|
||||
messages: list[str] = []
|
||||
assert manager.get_or_download("ASIN", notify=messages.append) is None
|
||||
assert "Download failed" in messages
|
||||
Reference in New Issue
Block a user