A Python port of the Invisible Internet Project (I2P)
at main 156 lines 6.2 kB view raw
1"""Tests for network probes — TDD: tests before implementation.""" 2 3import socket 4from unittest.mock import MagicMock, patch 5 6import pytest 7 8from i2p_apps.setup.network_probe import ( 9 BandwidthEstimate, 10 DnsProbeResult, 11 LatencyProbeResult, 12 NetworkProbeResult, 13 check_dns, 14 estimate_bandwidth, 15 measure_tcp_rtt, 16 probe_dns, 17 probe_latency, 18 run_network_probes, 19) 20 21 22class TestCheckDns: 23 def test_successful_resolution(self): 24 with patch("i2p_apps.setup.network_probe.socket.getaddrinfo") as mock: 25 mock.return_value = [(2, 1, 6, "", ("93.184.216.34", 0))] 26 success, latency = check_dns("example.com") 27 assert success is True 28 assert latency >= 0 29 30 def test_failed_resolution(self): 31 with patch("i2p_apps.setup.network_probe.socket.getaddrinfo") as mock: 32 mock.side_effect = socket.gaierror("Name resolution failed") 33 success, latency = check_dns("nonexistent.invalid") 34 assert success is False 35 assert latency == 0.0 36 37 38class TestProbeDns: 39 def test_all_domains_resolve(self): 40 with patch("i2p_apps.setup.network_probe.check_dns") as mock: 41 mock.return_value = (True, 10.0) 42 result = probe_dns() 43 assert isinstance(result, DnsProbeResult) 44 assert result.can_resolve_neutral is True 45 assert result.can_resolve_cdn is True 46 assert result.resolver_latency_ms > 0 47 48 def test_partial_resolution(self): 49 results = { 50 "example.com": (True, 10.0), 51 "cloudflare.com": (False, 0.0), 52 } 53 with patch("i2p_apps.setup.network_probe.check_dns") as mock: 54 mock.side_effect = lambda d: results.get(d, (False, 0.0)) 55 result = probe_dns() 56 assert result.can_resolve_neutral is True 57 assert result.can_resolve_cdn is False 58 59 60class TestMeasureTcpRtt: 61 def test_successful_connection(self): 62 mock_sock = MagicMock() 63 mock_sock.connect_ex.return_value = 0 64 with patch("i2p_apps.setup.network_probe.socket.socket", return_value=mock_sock): 65 rtt = measure_tcp_rtt("example.com", 443) 66 assert rtt is not None 67 assert rtt >= 0 68 69 def test_connection_timeout(self): 70 mock_sock = MagicMock() 71 mock_sock.connect_ex.side_effect = OSError("timeout") 72 with patch("i2p_apps.setup.network_probe.socket.socket", return_value=mock_sock): 73 rtt = measure_tcp_rtt("unreachable.invalid", 443) 74 assert rtt is None 75 76 77class TestProbeLatency: 78 def test_returns_latency_result(self): 79 with patch("i2p_apps.setup.network_probe.measure_tcp_rtt") as mock: 80 mock.return_value = 0.045 # 45ms 81 result = probe_latency(endpoints=["example.com:443", "cloudflare.com:443"]) 82 assert isinstance(result, LatencyProbeResult) 83 assert result.rtt_ms > 0 84 assert result.endpoints_reached > 0 85 86 def test_no_endpoints_reachable(self): 87 with patch("i2p_apps.setup.network_probe.measure_tcp_rtt", return_value=None): 88 result = probe_latency(endpoints=["unreachable.invalid:443"]) 89 assert result.endpoints_reached == 0 90 assert result.rtt_ms == 0.0 91 92 93class TestEstimateBandwidth: 94 def test_successful_download(self): 95 mock_resp = MagicMock() 96 mock_resp.read.return_value = b"x" * 102400 97 mock_resp.status = 200 98 mock_resp.__enter__ = lambda s: s 99 mock_resp.__exit__ = MagicMock(return_value=False) 100 101 with patch("i2p_apps.setup.network_probe.urllib.request.urlopen", 102 return_value=mock_resp): 103 result = estimate_bandwidth(url="https://example.com/test") 104 assert result is not None 105 assert isinstance(result, BandwidthEstimate) 106 assert result.download_mbps > 0 107 assert result.method == "cdn_download" 108 109 def test_download_failure(self): 110 with patch("i2p_apps.setup.network_probe.urllib.request.urlopen", 111 side_effect=OSError("Connection refused")): 112 result = estimate_bandwidth(url="https://unreachable.invalid/test") 113 assert result is None 114 115 116class TestRunNetworkProbes: 117 def test_full_probe(self): 118 with patch("i2p_apps.setup.network_probe.probe_dns") as mock_dns, \ 119 patch("i2p_apps.setup.network_probe.probe_latency") as mock_lat, \ 120 patch("i2p_apps.setup.network_probe.estimate_bandwidth") as mock_bw, \ 121 patch("i2p_apps.setup.network_probe.check_dns") as mock_check: 122 mock_dns.return_value = DnsProbeResult( 123 can_resolve_neutral=True, can_resolve_cdn=True, 124 can_resolve_reseed=True, resolver_latency_ms=10.0, 125 ) 126 mock_lat.return_value = LatencyProbeResult( 127 rtt_ms=45.0, jitter_ms=8.0, 128 endpoints_reached=3, endpoints_tested=3, 129 ) 130 mock_bw.return_value = BandwidthEstimate( 131 download_mbps=12.0, method="cdn_download", 132 ) 133 mock_check.return_value = (True, 10.0) 134 135 result = run_network_probes() 136 assert isinstance(result, NetworkProbeResult) 137 assert result.dns.can_resolve_neutral is True 138 assert result.latency.rtt_ms == 45.0 139 assert result.bandwidth is not None 140 141 def test_no_bandwidth_probe(self): 142 with patch("i2p_apps.setup.network_probe.probe_dns") as mock_dns, \ 143 patch("i2p_apps.setup.network_probe.probe_latency") as mock_lat, \ 144 patch("i2p_apps.setup.network_probe.check_dns") as mock_check: 145 mock_dns.return_value = DnsProbeResult( 146 can_resolve_neutral=True, can_resolve_cdn=True, 147 can_resolve_reseed=False, resolver_latency_ms=10.0, 148 ) 149 mock_lat.return_value = LatencyProbeResult( 150 rtt_ms=45.0, jitter_ms=8.0, 151 endpoints_reached=2, endpoints_tested=3, 152 ) 153 mock_check.return_value = (True, 10.0) 154 155 result = run_network_probes(include_bandwidth=False) 156 assert result.bandwidth is None