zapretgui/tests/test_net_failure.py
loop-uh 980496f80c
All checks were successful
Zapret source guards / validate (push) Successful in 9s
Проверки сети: одна отменяемая пауза вместо пяти копий, общий TLS-контекст без приватного импорта
- SocketCancel.sleep(): пауза на событии, «Стоп» обрывает её сразу, а не по
  опросу флага; Run.pause(): то же плюс внешний «Стоп» и общий лимит времени.
  Ими заменены reach.pause, sections._rest/_wait и два цикла ожидания в
  protocol_probe; передышка между соединениями к одному адресу больше не спит
  мимо «Стопа».
- tls_probe.client_context — публичный: volume_probe и upload_probe больше не
  берут приватную функцию соседнего модуля.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:50:36 +03:00

86 lines
3.4 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.

"""Общий словарь видов сетевого сбоя: вид определяется по коду ошибки, а не по тексту."""
from __future__ import annotations
import socket
import ssl
import unittest
from utils import net_failure as nf
def _win(code: int) -> OSError:
# Так Windows отдаёт ошибки Winsock, которые Python не перевёл в свои классы.
error = OSError(None, "сообщение на языке системы")
error.winerror = code
return error
class ClassifyTests(unittest.TestCase):
def test_python_exception_classes(self) -> None:
self.assertEqual(nf.classify(socket.timeout()), nf.FAILURE_TIMEOUT)
self.assertEqual(nf.classify(TimeoutError()), nf.FAILURE_TIMEOUT)
self.assertEqual(nf.classify(ConnectionRefusedError()), nf.FAILURE_REFUSED)
self.assertEqual(nf.classify(ConnectionResetError()), nf.FAILURE_RESET)
self.assertEqual(nf.classify(ConnectionAbortedError()), nf.FAILURE_RESET)
self.assertEqual(nf.classify(BrokenPipeError()), nf.FAILURE_RESET)
def test_windows_codes_win_over_the_message(self) -> None:
self.assertEqual(nf.classify(_win(10060)), nf.FAILURE_TIMEOUT)
self.assertEqual(nf.classify(_win(10061)), nf.FAILURE_REFUSED)
self.assertEqual(nf.classify(_win(10054)), nf.FAILURE_RESET)
self.assertEqual(nf.classify(_win(10051)), nf.FAILURE_UNREACHABLE)
self.assertEqual(nf.classify(_win(10065)), nf.FAILURE_UNREACHABLE)
def test_tls_failures(self) -> None:
self.assertEqual(nf.classify(ssl.SSLCertVerificationError()), nf.FAILURE_CERT)
self.assertEqual(nf.classify(ssl.SSLEOFError()), nf.FAILURE_CLOSED)
self.assertEqual(nf.classify(ssl.SSLError()), nf.FAILURE_TLS)
def test_unknown_is_other_not_a_guess(self) -> None:
self.assertEqual(nf.classify(OSError("непонятно что")), nf.FAILURE_OTHER)
self.assertEqual(nf.classify(ValueError()), nf.FAILURE_OTHER)
def test_dns_wire_speaks_the_same_vocabulary(self) -> None:
from utils import dns_wire
self.assertIs(dns_wire.FAILURE_TIMEOUT, nf.FAILURE_TIMEOUT)
self.assertEqual(dns_wire._failure_for(_win(10060)), nf.FAILURE_TIMEOUT)
if __name__ == "__main__":
unittest.main()
class CancellablePauseTests(unittest.TestCase):
"""Паузы между пробами снимает «Стоп» сразу, а не по окончании паузы."""
def test_socket_cancel_sleep_ends_at_stop(self) -> None:
import threading
import time
from utils.socket_cancel import SocketCancel
token = SocketCancel()
self.assertTrue(token.sleep(0.01))
threading.Timer(0.05, token.cancel).start()
started = time.monotonic()
self.assertFalse(token.sleep(5.0))
self.assertLess(time.monotonic() - started, 1.0)
self.assertFalse(token.sleep(5.0))
def test_run_pause_notices_an_outside_stop(self) -> None:
import time
from diagnostics.run_context import Run
stop = {"now": False}
run = Run(lambda: stop["now"], workers=1)
try:
self.assertTrue(run.pause(0.01))
stop["now"] = True
started = time.monotonic()
self.assertFalse(run.pause(5.0))
self.assertLess(time.monotonic() - started, 1.0)
finally:
run.close()