Files
shelfmark/tests/newznab/test_cache.py
blades 18a3f0bf44 Newznab capability (#867)
I've added a plugin using the same architecture as the prowlarr plugin
to enable Newznab as a source.
I've tested locally with nzbhydra2 and it all seems to work as intended.
I've added some unit tests for this feature, and found that a couple of
other unit tests weren't behaving so fixed those up while I was at it. I
also ran all of the linters in the makefile against it and fixed those
up, too, so hopefully this should be as clean and as compatible as it
can be.
2026-04-14 09:43:03 +01:00

94 lines
3.1 KiB
Python

"""Unit tests for the Newznab release cache."""
import time
from unittest.mock import patch
import pytest
from shelfmark.release_sources.newznab import cache as cache_module
from shelfmark.release_sources.newznab.cache import (
cache_release,
cleanup_expired,
get_release,
remove_release,
)
@pytest.fixture(autouse=True)
def clear_cache():
"""Ensure the cache is empty before and after each test."""
cache_module._cache.clear()
yield
cache_module._cache.clear()
class TestCacheRelease:
def test_stores_and_retrieves_release(self):
data = {"title": "My Book", "downloadUrl": "https://example.com/nzb/1"}
cache_release("id-1", data)
assert get_release("id-1") == data
def test_overwrites_existing_entry(self):
cache_release("id-1", {"title": "Old"})
cache_release("id-1", {"title": "New"})
assert get_release("id-1")["title"] == "New"
class TestGetRelease:
def test_returns_none_for_unknown_id(self):
assert get_release("no-such-id") is None
def test_returns_none_after_ttl_expires(self):
cache_release("id-ttl", {"title": "Expiring"})
past = time.time() - cache_module.RELEASE_CACHE_TTL - 1
cache_module._cache["id-ttl"] = (cache_module._cache["id-ttl"][0], past)
assert get_release("id-ttl") is None
def test_expired_entry_is_removed(self):
cache_release("id-evict", {"title": "Gone"})
past = time.time() - cache_module.RELEASE_CACHE_TTL - 1
cache_module._cache["id-evict"] = (cache_module._cache["id-evict"][0], past)
get_release("id-evict")
assert "id-evict" not in cache_module._cache
def test_fresh_entry_not_expired(self):
cache_release("id-fresh", {"title": "Fresh"})
# Advance time by less than TTL
future = time.time() + cache_module.RELEASE_CACHE_TTL - 60
with patch("shelfmark.release_sources.newznab.cache.time") as mock_time:
mock_time.time.return_value = future
result = get_release("id-fresh")
assert result is not None
class TestRemoveRelease:
def test_removes_existing_entry(self):
cache_release("id-remove", {"title": "To Remove"})
remove_release("id-remove")
assert get_release("id-remove") is None
def test_no_error_when_removing_absent_entry(self):
remove_release("no-such-id") # should not raise
class TestCleanupExpired:
def test_removes_only_expired_entries(self):
cache_release("fresh", {"title": "Fresh"})
cache_release("stale", {"title": "Stale"})
past = time.time() - cache_module.RELEASE_CACHE_TTL - 1
cache_module._cache["stale"] = (cache_module._cache["stale"][0], past)
removed = cleanup_expired()
assert removed == 1
assert get_release("fresh") is not None
assert "stale" not in cache_module._cache
def test_returns_zero_when_nothing_expired(self):
cache_release("a", {})
cache_release("b", {})
assert cleanup_expired() == 0
def test_returns_zero_when_cache_empty(self):
assert cleanup_expired() == 0