zapretgui/tests/test_my_network.py
loop-uh ea7b618c38
All checks were successful
Zapret source guards / validate (push) Successful in 10s
Windows-сборка / Dev Dev 21.1.7.188 опубликован
Единый источник слов для всех проверок, маскирование внешнего адреса, видеоузлы YouTube вашей сети
block_view решает строки и итоги сети, компьютера, хостингов, звонков, Telegram, DNS, скорости, места фильтра и сравнения: карточки и текстовый отчёт берут их оттуда, а журнал строит движок из того же словаря. Внешний адрес в отчёте скрыт (109.252.1.xxx), провайдер и сеть остаются. Видеоузлы берутся со страницы ролика и от redirector.googlevideo.com, у узла названа его сеть, а медленный первый узел сравнивается с запасным.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 11:02:18 -04:00

205 lines
10 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.

import unittest
from blockcheck.ui.result_cards_model import build_cards
from diagnostics import my_network as net
from utils.ip_owner import IpOwner
TRACE = b"fl=1\nh=one.one.one.one\nip=203.0.113.7\nts=1\nloc=RU\ntls=TLSv1.3\n"
OWNER = IpOwner(asn="12389", prefix="203.0.113.0/24", country="RU", owner="ROSTELECOM-AS")
class TraceTests(unittest.TestCase):
def test_address_and_country_are_read_from_trace(self) -> None:
self.assertEqual(net.parse_trace(TRACE), ("203.0.113.7", "RU"))
self.assertEqual(net.parse_trace("ip=2a00:1450::1\nloc=de"), ("2a00:1450::1", "DE"))
def test_garbage_gives_no_address(self) -> None:
for body in (b"", b"<html>blocked</html>", b"ip=not-an-address\nloc=RU"):
with self.subTest(body=body):
self.assertEqual(net.parse_trace(body)[0], "")
class CollectTests(unittest.TestCase):
def test_second_server_is_asked_when_the_first_is_silent(self) -> None:
asked = []
def fetch(server):
asked.append(server)
return None if server == net.TRACE_SERVERS[0] else TRACE
facts = net.collect(fetch=fetch, owner_of=lambda ip: OWNER, local=lambda: "192.168.1.5")
self.assertEqual(asked, list(net.TRACE_SERVERS))
self.assertEqual((facts.external_ip, facts.country, facts.owner, facts.local_ip), ("203.0.113.7", "RU", OWNER, "192.168.1.5"))
def test_owner_is_not_asked_without_an_address(self) -> None:
owners = []
facts = net.collect(fetch=lambda _server: None, owner_of=owners.append, local=lambda: "")
self.assertEqual(owners, [])
self.assertEqual(facts.external_ip, "")
class JudgeTests(unittest.TestCase):
def _lines(self, **facts):
return {line.name: line for line in net.judge(net.NetworkFacts(**facts))}
def test_provider_network_and_router(self) -> None:
lines = self._lines(external_ip="203.0.113.7", country="RU", owner=OWNER, local_ip="192.168.1.5")
self.assertEqual(lines["Внешний адрес"].text, "203.0.113.xxx (RU) — последние цифры скрыты, чтобы отчётом можно было делиться")
self.assertEqual(lines["Провайдер"].text, "ROSTELECOM-AS · AS12389, RU")
self.assertEqual(lines["Сеть"].text, "203.0.113.0/24")
self.assertIn("за роутером", lines["Адрес компьютера"].text)
def test_carrier_address_means_shared_address(self) -> None:
lines = self._lines(external_ip="203.0.113.7", owner=OWNER, local_ip="100.72.4.9")
self.assertIn("общим адресом", lines["Адрес компьютера"].text)
self.assertEqual(lines["Адрес компьютера"].state, "info")
def test_direct_connection(self) -> None:
lines = self._lines(external_ip="203.0.113.7", owner=OWNER, local_ip="203.0.113.7")
self.assertIn("прямое подключение", lines["Адрес компьютера"].text)
def test_public_local_address_that_differs_from_external_means_proxy_or_vpn(self) -> None:
lines = self._lines(external_ip="203.0.113.7", owner=OWNER, local_ip="8.8.4.4")
self.assertIn("прокси, VPN или общий адрес провайдера", lines["Адрес компьютера"].text)
def test_unknown_is_said_plainly(self) -> None:
lines = self._lines()
self.assertEqual(lines["Внешний адрес"].state, "unknown")
self.assertNotIn("Провайдер", lines)
no_owner = self._lines(external_ip="203.0.113.7")
self.assertEqual((no_owner["Провайдер"].state, no_owner["Провайдер"].text), ("unknown", "узнать не удалось"))
def test_other_bypass_tools_are_a_warning_not_a_vpn_verdict(self) -> None:
lines = {line.name: line for line in net.judge(net.NetworkFacts(external_ip="203.0.113.7"), bypass_tools=("WARP",))}
self.assertEqual(lines["Другие программы обхода и VPN"].state, "warn")
self.assertIn("WARP", lines["Другие программы обхода и VPN"].text)
class NetworkCardTests(unittest.TestCase):
def _card(self, network):
[card] = build_cards({"network": network})
return card
def test_card_names_the_provider(self) -> None:
card = self._card({
"external_ip": "203.0.113.7",
"provider": "ROSTELECOM-AS · AS12389",
"lines": [{"state": "info", "name": "Внешний адрес", "text": "203.0.113.7 (RU)"}],
})
self.assertEqual((card.key, card.title, card.status, card.level), ("network", "Ваша сеть", "ROSTELECOM-AS · AS12389", "info"))
self.assertEqual(card.lines[0].text, "203.0.113.7 (RU)")
self.assertFalse(card.site)
def test_card_without_answer_and_with_warning(self) -> None:
self.assertEqual(self._card({"lines": []}).status, "Не удалось узнать")
self.assertEqual(self._card({"lines": []}).level, "unknown")
self.assertEqual(self._card({"external_ip": "1.2.3.4", "lines": []}).status, "Провайдер не определён")
warned = self._card({"external_ip": "1.2.3.4", "lines": [{"state": "warn", "name": "VPN", "text": "WARP"}]})
self.assertEqual(warned.level, "warn")
if __name__ == "__main__":
unittest.main()
def _sample(address="192.168.1.1", answered=5, avg=2.0, sent=5):
return net.HopSample(address, sent, answered, avg if answered else None)
def _link(router=None, beyond=None, internet=None):
facts = net.NetworkFacts(
external_ip="109.252.1.1",
local_ip="192.168.1.8",
router=router or _sample(),
beyond=beyond,
internet=internet or _sample("1.1.1.1", avg=14.0),
)
return {line.name: line for line in net.judge(facts)}
class HomeLinkTests(unittest.TestCase):
"""Связь внутри своей сети: потери называются там, где они начинаются."""
def test_healthy_link_is_said_to_be_fine(self) -> None:
lines = _link(beyond=_sample("100.64.0.1"))
self.assertEqual((lines["Роутер"].state, lines["Связь с интернетом"].state), ("ok", "ok"))
self.assertIn("192.168.1.1 — отвечает за 2 мс, потерь нет", lines["Роутер"].text)
self.assertIn("CGNAT", lines["За роутером"].text)
def test_losses_to_the_router_are_a_home_problem(self) -> None:
lines = _link(router=_sample(answered=3), internet=_sample("1.1.1.1", answered=2))
self.assertEqual(lines["Роутер"].state, "warn")
self.assertIn("теряется 2 из 5", lines["Роутер"].text)
self.assertIn("слабом Wi‑Fi", lines["Роутер"].text)
self.assertIn("начинаются уже до роутера", lines["Связь с интернетом"].text)
def test_losses_only_beyond_the_router_are_the_provider(self) -> None:
lines = _link(internet=_sample("1.1.1.1", answered=3))
self.assertEqual((lines["Роутер"].state, lines["Связь с интернетом"].state), ("ok", "warn"))
self.assertIn("у провайдера", lines["Связь с интернетом"].text)
def test_one_lost_packet_is_not_a_finding(self) -> None:
lines = _link(router=_sample(answered=4), internet=_sample("1.1.1.1", answered=4))
self.assertEqual((lines["Роутер"].state, lines["Связь с интернетом"].state), ("ok", "ok"))
def test_slow_router_points_at_weak_wifi(self) -> None:
line = _link(router=_sample(avg=85.0))["Роутер"]
self.assertEqual(line.state, "warn")
self.assertIn("слабый сигнал Wi‑Fi", line.text)
def test_silence_is_not_called_a_fault(self) -> None:
lines = _link(router=_sample(answered=0), internet=_sample("1.1.1.1", answered=0))
# Роутер и провайдер вправе не отвечать на пинг.
self.assertNotIn("Роутер", lines)
self.assertEqual(lines["Связь с интернетом"].state, "unknown")
self.assertEqual(_link(router=_sample(answered=0))["Роутер"].state, "info")
def test_second_router_and_direct_connection_are_named(self) -> None:
self.assertIn("ещё один роутер", _link(beyond=_sample("192.168.0.1"))["За роутером"].text)
self.assertIn("внутренняя сеть провайдера", _link(beyond=_sample("10.20.0.1"))["За роутером"].text)
direct = _link(router=_sample("109.252.0.1"))
self.assertIn("без домашнего роутера", direct["Роутер"].text)
self.assertNotIn("За роутером", direct)
def test_without_ping_there_are_no_link_lines(self) -> None:
lines = {line.name for line in net.judge(net.NetworkFacts(external_ip="109.252.1.1", local_ip="192.168.1.8"))}
self.assertFalse({"Роутер", "Связь с интернетом"} & lines)
def test_measuring_counts_answers_and_averages_time(self) -> None:
answers = iter([("192.168.1.1", 2.0), None, ("192.168.1.1", 4.0), None, ("192.168.1.1", None)])
sample = net.measure_hop(lambda _ttl: next(answers), 1)
self.assertEqual((sample.address, sample.sent, sample.answered, sample.lost, sample.avg_ms), ("192.168.1.1", 5, 3, 2, 3.0))
def unsupported(_ttl):
raise NotImplementedError
self.assertIsNone(net.measure_hop(unsupported, 1))
def test_collect_measures_router_next_hop_and_internet(self) -> None:
asked: list[int] = []
def probe(ttl):
asked.append(ttl)
return ("1.1.1.1" if ttl == net.FAR_TTL else f"10.0.0.{ttl}", 5.0)
facts = net.collect(fetch=lambda _server: None, owner_of=lambda _ip: None, local=lambda: "", probe=probe)
self.assertEqual(sorted(set(asked)), [1, 2, net.FAR_TTL])
self.assertEqual((facts.router.address, facts.beyond.address, facts.internet.address), ("10.0.0.1", "10.0.0.2", "1.1.1.1"))