""" Тесты модуля tests/utils/tls.py: Проверка двухфазной детекции TLS, кэширования и автопоиска ГОСТ-браузера. """ import ssl from unittest.mock import patch, MagicMock import pytest from tests.utils.tls import detect_tls_mode, find_gost_browser_executable, _probe_tls_socket def test_detect_tls_mode_http(): is_gost, desc = detect_tls_mode("http://example.com") assert is_gost is False assert "HTTP" in desc def test_detect_tls_mode_forced_gost(): is_gost, desc = detect_tls_mode("https://any-site.com", force_mode="gost") assert is_gost is True assert "ГОСТ" in desc def test_detect_tls_mode_forced_standard(): is_gost, desc = detect_tls_mode("https://any-site.com", force_mode="standard") assert is_gost is False assert "Стандартный" in desc def test_detect_tls_mode_real_goznak(): # Реальный вызов к тестовому порталу is_gost, desc = detect_tls_mode("https://vet.goznak.ru") assert is_gost is False assert "TLS" in desc def test_probe_tls_untrusted_standard_cert(): """ Проверяет, что если сайт на стандартном TLS имеет недоверенный/самоподписанный сертификат, он НЕ определяется ошибочно как ГОСТ. """ with patch("ssl.create_default_context") as mock_def_ctx, \ patch("ssl._create_unverified_context") as mock_unv_ctx, \ patch("socket.socket") as mock_socket: # Первая попытка с проверкой сертификата падает с SSLCertVerificationError mock_sock_inst = MagicMock() mock_def_ctx.return_value.wrap_socket.side_effect = ssl.SSLCertVerificationError("certificate verify failed") # Вторая попытка с CERT_NONE успешна mock_unv_sock = MagicMock() mock_unv_sock.version.return_value = "TLSv1.3" mock_unv_sock.cipher.return_value = ("TLS_AES_256_GCM_SHA384", "TLSv1.3", 256) mock_unv_ctx.return_value.wrap_socket.return_value.__enter__.return_value = mock_unv_sock is_gost, desc = _probe_tls_socket("self-signed.example.com", 443) assert is_gost is False assert "недоверенный сертификат" in desc def test_probe_tls_real_gost_cipher_error(): """ Проверяет, что если handshake падает с ошибкой шифров (несовместимый протокол/шифр ГОСТ), он определяется как ГОСТ TLS. """ with patch("ssl.create_default_context") as mock_def_ctx, \ patch("ssl._create_unverified_context") as mock_unv_ctx, \ patch("socket.socket") as mock_socket: mock_def_ctx.return_value.wrap_socket.side_effect = ssl.SSLError(ssl.SSL_ERROR_SSL, "UNSUPPORTED_PROTOCOL") mock_unv_ctx.return_value.wrap_socket.side_effect = ssl.SSLError(ssl.SSL_ERROR_SSL, "NO_CIPHERS_AVAILABLE") is_gost, desc = _probe_tls_socket("gost.example.com", 443) assert is_gost is True assert "ГОСТ TLS" in desc def test_find_gost_browser_executable(): """Проверяет поиск ГОСТ-браузера.""" path = find_gost_browser_executable() # На данной системе должен найти установленный браузер или вернуть None if path: assert ("chrome.exe" in path.lower()) or ("browser.exe" in path.lower())