ZaStoGram_desktop/Telegram/SourceFiles/tests/test_proxy_logging_events.py
loop-uh f6e48891f9
All checks were successful
Desktop source guards / guards (push) Successful in 5s
Запускать проверки во всех source-гардах и обновить устаревшие
Скрипт выпуска и CI запускают каждый гард из release_guards.txt как
`python <файл>` и смотрят только на код возврата. Семь файлов не вызывали
свои test_* вовсе и проходили, ничего не проверив, а в трёх ручной список
вызовов отстал на один новый тест. Теперь каждый гард вызывает все свои
test_* сам, тем же блоком, что уже стоял в test_web_proxy_carrier_flow.py,
а новый гард test_release_guards_run_their_tests.py следит, чтобы так
оставалось у всех файлов списка.

Под запуском всплыли устаревшие проверки, сломанные коммитом 744109cc78
(«Pace MTProxy dials instead of steering them»):

- он намеренно убрал подстройку MTProxy под кэш возможностей и
  принудительный ChromeModern: профиль ClientHello остаётся тем, что выбрал
  пользователь. Проверки в test_mtproxy_target_flow.py и
  test_proxy_capability_cache.py требовали старое поведение и теперь
  требуют новое: в ветке MTProxy нет обращения к кэшу, а
  BoringMtproxyStealthOptions сохраняет выбранный профиль;
- reportMtproxySuccess удалён, поэтому проверка «первые данные отмечаются
  один раз на сокет» смотрит на то, что сейчас стоит под этой защитой:
  прогресс, событие диагностики и noteDataPathSuccess;
- память маршрутов он оставил, но код переписан: проверка порядка
  (ответившие адреса, затем неопробованные, затем неудачные) идёт по
  нынешнему виду routeOrder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:27:08 +03:00

102 lines
2.9 KiB
Python

from pathlib import Path
from session_private_sources import read_session_private_sources
SOURCE_DIR = Path(__file__).resolve().parents[1]
PROXY_DIR = SOURCE_DIR / "mtproto" / "proxy"
MTPROXY_DIR = PROXY_DIR / "mtproxy"
DIAGNOSTICS_H = PROXY_DIR / "diagnostics.h"
DIAGNOSTICS_CPP = PROXY_DIR / "diagnostics.cpp"
RESOLVING_CPP = PROXY_DIR / "resolving_connection.cpp"
TLS_SOCKET_CPP = MTPROXY_DIR / "tls_socket.cpp"
TLS_SOCKET_HANDSHAKE_CPP = MTPROXY_DIR / "tls_socket_handshake.cpp"
TRANSPORT_POLICY_CPP = PROXY_DIR / "transport_policy.cpp"
SESSION_CPP = SOURCE_DIR / "mtproto" / "session" / "private" / "session_private.cpp"
def read(path):
assert path.exists(), f"missing expected source file: {path}"
return path.read_text(encoding="utf-8")
def function_body(text: str, signature: str) -> str:
start = text.index(signature)
brace = text.index(" {\n", start) + 1
depth = 0
for index in range(brace, len(text)):
char = text[index]
if char == "{":
depth += 1
elif char == "}":
depth -= 1
if depth == 0:
return text[brace + 1:index]
raise AssertionError(f"body not found for {signature}")
def test_diagnostics_declares_structured_proxy_events_and_context():
header = read(DIAGNOSTICS_H)
source = read(DIAGNOSTICS_CPP)
for event in (
"AdmissionQueued",
"AdmissionStarted",
"AdmissionCancelled",
"RouteSelected",
"RouteFailed",
"CanonicalDegraded",
"CanonicalRecovered",
"StealthRecipeApplied",
"TransportFallbackApplied",
):
assert f"ProxyDiagnosticsPhase::{event}" in source
assert event in header
for text in (
"admission_queued",
"admission_started",
"admission_cancelled",
"route_selected",
"route_failed",
"canonical_degraded",
"canonical_recovered",
"stealth_recipe_applied",
"transport_fallback_applied",
):
assert f'u"{text}"_q' in source
for field in (
"QString canonical",
"QString route",
"QString proxyKeyHash",
"QString profile",
"std::optional<int> recipeLevel",
"std::optional<bool> pskOffered",
"std::optional<bool> fragmentedClientHello",
"QString phaseAtFailure",
"std::optional<crl::time> queueMs",
):
assert field in header
for token in (
"canonical=%1",
"route=%1",
"proxy_key_hash=%1",
"profile=%1",
"recipe_level=%1",
"psk_offered=%1",
"fragmented_ch=%1",
"phase_at_failure=%1",
"queue_ms=%1",
):
assert token in source
assert "ProxyKeyHash(" in source
assert "QCryptographicHash::Sha256" in source
if __name__ == "__main__":
for name, value in list(globals().items()):
if name.startswith("test_") and callable(value):
value()
print("ok")