"""Magazine sources: parsing, host restriction, size/type checks. No network."""
import os
import tempfile
import unittest
from pathlib import Path
os.environ.setdefault("CONFIG_DIR", tempfile.mkdtemp(prefix="ttvc-test-config-"))
from core import magazine_sources as ms
class FakeResp:
def __init__(self, status=200, body=b"", headers=None, json_data=None):
self.status_code = status
self._body = body
self.headers = headers or {}
self._json = json_data
self.is_redirect = status in (301, 302, 303, 307, 308)
def json(self):
if self._json is None:
raise ValueError("no json")
return self._json
def iter_content(self, n):
for i in range(0, len(self._body), n):
yield self._body[i:i + n]
def close(self):
pass
class FakeSession:
def __init__(self, routes):
self.routes = routes
self.calls = []
def get(self, url, **kw):
self.calls.append(url)
for prefix, resp in self.routes.items():
if url.startswith(prefix):
return resp() if callable(resp) else resp
return FakeResp(404)
OPDS = b"""
c't 12/2026HeiseIssue
Elsewhere
EPUB only
"""
class OpdsTests(unittest.TestCase):
def provider(self, routes):
return ms.OpdsProvider("opds-1", "NAS", "http://nas.local:8083/opds/", FakeSession(routes))
def test_search_keeps_only_same_host_pdf_entries(self):
# Most specific route first: the fake session matches by prefix.
p = self.provider({"http://nas.local:8083/opds/search": FakeResp(body=OPDS),
"http://nas.local:8083/opds/": FakeResp(body=b'')})
items = p.search("ct")
self.assertEqual([i.title for i in items], ["c't 12/2026"])
self.assertEqual(items[0].id, "http://nas.local:8083/dl/1.pdf")
self.assertEqual(items[0].thumb_url, "http://nas.local:8083/thumb/1.jpg")
def test_resolve_rejects_other_hosts(self):
p = self.provider({})
with self.assertRaises(ms.SourceError):
p.resolve_pdf("http://169.254.169.254/latest/meta-data")
def test_doctype_and_entities_are_refused(self):
evil = b']>'
with self.assertRaises(ms.SourceError):
ms.parse_xml_safely(evil)
def test_malformed_feed_is_a_source_error(self):
with self.assertRaises(ms.SourceError):
ms.parse_xml_safely(b"login