A Python port of the Invisible Internet Project (I2P)
at main 249 lines 8.0 kB view raw
1"""Tests for extended PeerProfile with full profiling metrics.""" 2 3import os 4import time 5 6import pytest 7 8 9class TestPeerProfileExtended: 10 """Tests for the extended PeerProfile fields and methods.""" 11 12 def test_initial_state(self): 13 from i2p_peer.profile import PeerProfile 14 15 h = os.urandom(32) 16 p = PeerProfile(router_hash=h) 17 assert p.router_hash == h 18 assert p.tunnel_builds_succeeded == 0 19 assert p.tunnel_builds_failed == 0 20 assert p.tunnel_builds_rejected == 0 21 assert p.send_success_count == 0 22 assert p.send_failure_count == 0 23 assert p.db_store_success_count == 0 24 assert p.db_store_failure_count == 0 25 assert p.db_lookup_success_count == 0 26 assert p.db_lookup_failure_count == 0 27 assert p.last_heard_from == 0.0 28 assert p.first_heard_about == 0.0 29 assert p.last_send_success == 0.0 30 assert p.last_send_failure == 0.0 31 assert p.capacity == 0.0 32 assert p.speed == 0.0 33 assert p.integration == 0.0 34 assert p.is_expanding is False 35 assert p.is_active is True 36 assert p.is_banned is False 37 assert p.ban_expiry == 0.0 38 39 def test_tunnel_build_success_rate(self): 40 from i2p_peer.profile import PeerProfile 41 42 p = PeerProfile(os.urandom(32)) 43 for _ in range(7): 44 p.record_tunnel_build_success() 45 for _ in range(3): 46 p.record_tunnel_build_failure() 47 assert p.tunnel_builds_succeeded == 7 48 assert p.tunnel_builds_failed == 3 49 assert abs(p.tunnel_success_rate - 0.7) < 0.001 50 51 def test_tunnel_success_rate_no_builds(self): 52 from i2p_peer.profile import PeerProfile 53 54 p = PeerProfile(os.urandom(32)) 55 assert p.tunnel_success_rate == 0.0 56 57 def test_tunnel_build_rejection(self): 58 from i2p_peer.profile import PeerProfile 59 60 p = PeerProfile(os.urandom(32)) 61 p.record_tunnel_build_rejection() 62 p.record_tunnel_build_rejection() 63 assert p.tunnel_builds_rejected == 2 64 65 def test_send_success_rate(self): 66 from i2p_peer.profile import PeerProfile 67 68 p = PeerProfile(os.urandom(32)) 69 for _ in range(8): 70 p.record_send_success() 71 for _ in range(2): 72 p.record_send_failure() 73 assert p.send_success_count == 8 74 assert p.send_failure_count == 2 75 assert abs(p.send_success_rate - 0.8) < 0.001 76 77 def test_send_success_rate_no_sends(self): 78 from i2p_peer.profile import PeerProfile 79 80 p = PeerProfile(os.urandom(32)) 81 assert p.send_success_rate == 0.0 82 83 def test_db_success_rate(self): 84 from i2p_peer.profile import PeerProfile 85 86 p = PeerProfile(os.urandom(32)) 87 for _ in range(5): 88 p.record_db_store_success() 89 for _ in range(3): 90 p.record_db_lookup_success() 91 for _ in range(2): 92 p.record_db_store_failure() 93 # 8 success out of 10 total 94 assert abs(p.db_success_rate - 0.8) < 0.001 95 96 def test_db_success_rate_no_ops(self): 97 from i2p_peer.profile import PeerProfile 98 99 p = PeerProfile(os.urandom(32)) 100 assert p.db_success_rate == 0.0 101 102 def test_latency_recording(self): 103 from i2p_peer.profile import PeerProfile 104 105 p = PeerProfile(os.urandom(32)) 106 p.record_latency(100.0) 107 p.record_latency(200.0) 108 p.record_latency(300.0) 109 assert abs(p.average_latency - 200.0) < 0.001 110 111 def test_latency_no_samples(self): 112 from i2p_peer.profile import PeerProfile 113 114 p = PeerProfile(os.urandom(32)) 115 assert p.average_latency == 0.0 116 117 def test_latency_max_samples(self): 118 from i2p_peer.profile import PeerProfile 119 120 p = PeerProfile(os.urandom(32)) 121 # Fill with 50 samples of 100ms 122 for _ in range(50): 123 p.record_latency(100.0) 124 # Add 10 more of 200ms (should evict oldest) 125 for _ in range(10): 126 p.record_latency(200.0) 127 # Should have 50 samples: 40 * 100 + 10 * 200 = 6000 / 50 = 120 128 assert abs(p.average_latency - 120.0) < 0.001 129 130 def test_ban_and_unban(self): 131 from i2p_peer.profile import PeerProfile 132 133 p = PeerProfile(os.urandom(32)) 134 assert not p.is_currently_banned 135 p.ban(60.0) # 60 seconds 136 assert p.is_banned is True 137 assert p.ban_expiry > time.time() 138 assert p.is_currently_banned 139 p.unban() 140 assert p.is_banned is False 141 assert not p.is_currently_banned 142 143 def test_ban_expiry(self): 144 from i2p_peer.profile import PeerProfile 145 146 p = PeerProfile(os.urandom(32)) 147 # Ban for 0 seconds (immediately expired) 148 p.ban(0.0) 149 assert not p.is_currently_banned 150 151 def test_heard_from_updates_timestamp(self): 152 from i2p_peer.profile import PeerProfile 153 154 p = PeerProfile(os.urandom(32)) 155 assert p.last_heard_from == 0.0 156 before = time.time() 157 p.heard_from() 158 after = time.time() 159 assert before <= p.last_heard_from <= after 160 161 def test_first_heard_about_set_once(self): 162 from i2p_peer.profile import PeerProfile 163 164 p = PeerProfile(os.urandom(32)) 165 p.heard_from() 166 first = p.first_heard_about 167 assert first > 0.0 168 time.sleep(0.01) 169 p.heard_from() 170 # first_heard_about should not change 171 assert p.first_heard_about == first 172 173 def test_to_dict_from_dict_roundtrip(self): 174 from i2p_peer.profile import PeerProfile 175 176 h = os.urandom(32) 177 p = PeerProfile(h) 178 for _ in range(5): 179 p.record_tunnel_build_success() 180 for _ in range(2): 181 p.record_tunnel_build_failure() 182 p.record_tunnel_build_rejection() 183 for _ in range(3): 184 p.record_send_success() 185 p.record_send_failure() 186 p.record_db_store_success() 187 p.record_db_lookup_failure() 188 p.record_latency(150.0) 189 p.record_latency(250.0) 190 p.heard_from() 191 p.capacity = 0.75 192 p.speed = 0.6 193 p.integration = 0.5 194 p.is_expanding = True 195 196 d = p.to_dict() 197 p2 = PeerProfile.from_dict(d) 198 199 assert p2.router_hash == h 200 assert p2.tunnel_builds_succeeded == 5 201 assert p2.tunnel_builds_failed == 2 202 assert p2.tunnel_builds_rejected == 1 203 assert p2.send_success_count == 3 204 assert p2.send_failure_count == 1 205 assert p2.db_store_success_count == 1 206 assert p2.db_lookup_failure_count == 1 207 assert abs(p2.capacity - 0.75) < 0.001 208 assert abs(p2.speed - 0.6) < 0.001 209 assert abs(p2.integration - 0.5) < 0.001 210 assert p2.is_expanding is True 211 assert len(p2._latency_samples) == 2 212 assert p2.last_heard_from == p.last_heard_from 213 214 def test_is_established(self): 215 from i2p_peer.profile import PeerProfile 216 217 p = PeerProfile(os.urandom(32)) 218 # Not established with no history 219 assert not p.is_established 220 # Need at least some tunnel builds and sends 221 for _ in range(5): 222 p.record_tunnel_build_success() 223 for _ in range(5): 224 p.record_send_success() 225 assert p.is_established 226 227 def test_record_db_lookup_success(self): 228 from i2p_peer.profile import PeerProfile 229 230 p = PeerProfile(os.urandom(32)) 231 p.record_db_lookup_success() 232 assert p.db_lookup_success_count == 1 233 234 def test_record_db_lookup_failure(self): 235 from i2p_peer.profile import PeerProfile 236 237 p = PeerProfile(os.urandom(32)) 238 p.record_db_lookup_failure() 239 assert p.db_lookup_failure_count == 1 240 241 def test_send_timestamps_updated(self): 242 from i2p_peer.profile import PeerProfile 243 244 p = PeerProfile(os.urandom(32)) 245 before = time.time() 246 p.record_send_success() 247 assert p.last_send_success >= before 248 p.record_send_failure() 249 assert p.last_send_failure >= before