zapretgui/tests/test_blockcheck_requests_transport.py
loop-uh a8ac7b2c8a
All checks were successful
Zapret source guards / validate (push) Successful in 9s
Windows-сборка / Dev Dev 21.1.7.36 опубликован
Проверки сети: общая основа для запросов DNS — у каждого способа связи своя функция (обычный DNS по UDP и по TCP, шифрованный DoT на порту 853 и DoH на порту 443), запрос можно снять кнопкой «Стоп», а вместо текста ошибки возвращается вид сбоя: сервер молчит, порт закрыт, соединение оборвано, чужой сертификат, ошибка HTTP; эталонных серверов для сравнения ответов теперь четыре вместо двух и список один на BlockCheck и «Проверку домена» — если провайдер закрыл один из них (как 8.8.8.8), BlockCheck и «DNS подмена» называют его с причиной и советуют не выбирать для защищённого DNS; перехват DNS по контрольному адресу, виды адресов-заглушек и отмена запросов сведены в одно место вместо двух-трёх копий с разной логикой; адрес внутренней сети провайдера (100.64.0.0/10) в ответе DNS считается подменой; удалена старая проверка, которую никто не вызывал (preflight, isp_page_detector, ping_tester) вместе с её настройками и моделями
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:59:00 +03:00

90 lines
2.6 KiB
Python

"""BlockCheck использует общий HTTP-механизм приложения без отдельного httpx."""
from __future__ import annotations
import sys
import unittest
from pathlib import Path
from unittest.mock import patch
PROJECT_ROOT = Path(__file__).resolve().parents[1]
PROJECT_SRC = PROJECT_ROOT / "src"
if str(PROJECT_SRC) not in sys.path:
sys.path.insert(0, str(PROJECT_SRC))
from blockcheck.googlevideo_discovery import _fetch_watch_page # noqa: E402
class _Response:
def __init__(
self,
*,
chunks: tuple[bytes, ...] = (),
json_data: dict | None = None,
text: str = "",
status_code: int = 200,
history: tuple[object, ...] = (),
) -> None:
self._chunks = chunks
self._json_data = json_data or {}
self.text = text
self.status_code = status_code
self.history = history
def __enter__(self):
return self
def __exit__(self, *_args) -> None:
return None
def raise_for_status(self) -> None:
return None
def iter_content(self, chunk_size: int):
self.chunk_size = chunk_size
yield from self._chunks
def json(self) -> dict:
return self._json_data
class _Session:
def __init__(self, response: _Response) -> None:
self.response = response
self.max_redirects = None
self.calls: list[tuple[str, dict]] = []
def __enter__(self):
return self
def __exit__(self, *_args) -> None:
return None
def get(self, url: str, **kwargs):
self.calls.append((url, kwargs))
return self.response
class RequestsDependencyBoundaryTests(unittest.TestCase):
def test_retired_httpx_is_absent_from_runtime_and_blockcheck(self) -> None:
runtime = (PROJECT_ROOT / "requirements-runtime.txt").read_text("utf-8")
sources = (PROJECT_SRC / "blockcheck" / "googlevideo_discovery.py").read_text("utf-8")
self.assertNotIn("httpx", runtime.lower())
self.assertNotIn("httpx", sources.lower())
def test_googlevideo_download_stays_streamed_and_limited(self) -> None:
host = b"https://rr7---sn-user.googlevideo.com/videoplayback"
session = _Session(_Response(chunks=(b"prefix", host, b"unused")))
with patch("requests.Session", return_value=session):
page = _fetch_watch_page("https://youtube.example/watch", 4, lambda: False)
self.assertIn("rr7---sn-user.googlevideo.com", page)
self.assertTrue(session.calls[0][1]["stream"])
self.assertEqual(session.max_redirects, 5)
if __name__ == "__main__":
unittest.main()