zapretgui/tests/test_freeze_recheck.py
loop-uh 407cc43d70
All checks were successful
Zapret source guards / validate (push) Successful in 9s
BlockCheck: свои записи hosts — не замечание; VPN — только когда через него идёт интернет; причина — по главному адресу
- записи в hosts, которые внесла сама программа («Редактор hosts»), показаны
  как «всё в порядке»; перечисляются только чужие записи;
- подключённый VPN-адаптер без дороги в интернет (Radmin VPN, простаивающий
  Tailscale) больше не объявляется «проверки показывают сеть VPN»; про
  запущенные программы обхода сказано «если они сейчас включены»;
- причина и совет по сервису берутся у главного адреса: чужой сертификат у
  побочного адреса не подменяет настоящую причину;
- отпечаток JA4 приветствия «как Chrome» закреплён тестом: это тот самый
  отпечаток, который режет фильтр; вывод уточнён до «в Chrome может не
  открываться, а в Firefox — открываться».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:40:48 +03:00

109 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Обрыв на 16–20 КБ называется обрывом, только если повторился на том же сервере."""
from __future__ import annotations
import unittest
from diagnostics import freeze_check
from diagnostics.freeze_check import FreezeState
from diagnostics.tls_probe import ProbeResult
CUT = ProbeResult(ip="1.1.1.1", kind="ok", body_size=16_500, body_cut=True)
FULL = ProbeResult(ip="1.1.1.1", kind="ok", body_size=70_000)
TARGET = [{"id": "X-01", "provider": "X", "url": "https://x.example/file.bin"}]
def _check(answers):
asked = []
def _download(host, path):
asked.append((host, path))
return answers[min(len(asked), len(answers)) - 1]
server = freeze_check._check_provider("X", TARGET, _download, lambda: True)
return server, asked
class FreezeRecheckTests(unittest.TestCase):
def test_cut_twice_in_a_row_is_a_freeze(self) -> None:
server, asked = _check([CUT, CUT])
self.assertEqual((server.state, len(asked)), (FreezeState.FREEZE, 2))
self.assertIn("дважды подряд", server.text)
def test_cut_that_does_not_repeat_is_not_a_freeze(self) -> None:
server, asked = _check([CUT, FULL])
self.assertEqual((server.state, len(asked)), (FreezeState.OK, 2))
self.assertIn("первый обрыв был случайным сбоем", server.text)
def test_cut_without_a_clear_repeat_stays_unknown(self) -> None:
server, _asked = _check([CUT, None])
self.assertEqual(server.state, FreezeState.UNKNOWN)
self.assertIn("не подтвердился", server.text)
def test_clean_download_is_not_repeated(self) -> None:
server, asked = _check([FULL])
self.assertEqual((server.state, len(asked)), (FreezeState.OK, 1))
if __name__ == "__main__":
unittest.main()
class UnknownZapretStateTests(unittest.TestCase):
"""«Не удалось узнать, запущен ли Zapret» — не «не запущен»: запускать его не советуем."""
def test_start_is_advised_only_when_zapret_is_known_to_be_off(self) -> None:
from diagnostics import problems
from diagnostics.verdict import ReachState, _ADVICE_START, _advice_for
self.assertEqual(problems._zapret_action(False), "start_zapret")
self.assertEqual(problems._zapret_action(None), "strategy")
self.assertEqual(problems._zapret_action(True), "strategy")
self.assertEqual(_advice_for([ReachState.DPI], zapret_running=False), (_ADVICE_START,))
self.assertNotIn(_ADVICE_START, _advice_for([ReachState.DPI], zapret_running=None))
def test_closed_address_is_never_told_to_start_zapret(self) -> None:
from diagnostics.block_kind import KIND_IP
from diagnostics.verdict import ReachState, _ADVICE_START, _advice_for
self.assertNotIn(_ADVICE_START, _advice_for([ReachState.DPI], zapret_running=False, kind=KIND_IP))
def test_freeze_advice_follows_the_same_rule(self) -> None:
from diagnostics.freeze_check import FreezeServer, summarize_freeze
frozen = tuple(FreezeServer(f"S{i}", FreezeState.FREEZE, "обрыв") for i in range(4))
self.assertIn("Запустите Zapret", summarize_freeze(frozen, zapret_running=False).advice[0])
self.assertNotIn("Запустите Zapret", summarize_freeze(frozen, zapret_running=None).advice[0])
class LeadingCauseTests(unittest.TestCase):
"""Причина и совет берутся у главного адреса, а не у того, где чужой сертификат."""
def _verdict(self, main, second):
from diagnostics.verdict import DnsState, TargetOutcome, summarize_service
outcomes = [
TargetOutcome(host="x.com", purpose="сайт", reach=main, dns=DnsState.OK, main=True),
TargetOutcome(host="cdn.x.com", purpose="картинки", reach=second, dns=DnsState.OK),
]
return summarize_service("X", outcomes, zapret_running=True)
def test_foreign_certificate_on_a_side_address_does_not_hide_the_real_cause(self) -> None:
from diagnostics.verdict import ReachState, _ADVICE_CERT, _ADVICE_STRATEGY
verdict = self._verdict(ReachState.DPI, ReachState.CERT)
self.assertNotIn("чужой", verdict.headline)
self.assertEqual(verdict.advice[:2], (_ADVICE_STRATEGY, _ADVICE_CERT))
def test_foreign_certificate_on_the_main_address_is_still_the_cause(self) -> None:
from diagnostics.verdict import ReachState, _ADVICE_CERT
verdict = self._verdict(ReachState.CERT, ReachState.DPI)
self.assertIn("чужой", verdict.headline)
self.assertEqual(verdict.advice[0], _ADVICE_CERT)