A Python port of the Invisible Internet Project (I2P)
at main 114 lines 3.9 kB view raw
1"""Tests for packet scheduler and congestion control.""" 2 3import pytest 4 5 6class TestRetransmitTimer: 7 def test_initial_rto(self): 8 from i2p_streaming.scheduler import RetransmitTimer 9 timer = RetransmitTimer() 10 assert timer.rto == 3000 # Initial RTO: 3 seconds 11 12 def test_update_rtt(self): 13 from i2p_streaming.scheduler import RetransmitTimer 14 timer = RetransmitTimer() 15 timer.update_rtt(100) # 100ms RTT 16 assert timer.rto > 0 17 assert timer.rto < 3000 # Should be less than initial 18 19 def test_backoff(self): 20 from i2p_streaming.scheduler import RetransmitTimer 21 timer = RetransmitTimer() 22 rto1 = timer.rto 23 timer.backoff() 24 assert timer.rto == rto1 * 2 25 26 def test_max_backoff(self): 27 from i2p_streaming.scheduler import RetransmitTimer 28 timer = RetransmitTimer() 29 for _ in range(20): 30 timer.backoff() 31 assert timer.rto <= 60000 # Max 60 seconds 32 33 def test_update_rtt_smoothing(self): 34 from i2p_streaming.scheduler import RetransmitTimer 35 timer = RetransmitTimer() 36 timer.update_rtt(100) 37 rto1 = timer.rto 38 timer.update_rtt(200) 39 rto2 = timer.rto 40 # RTO should change but be smoothed 41 assert rto2 != rto1 42 43 44class TestCongestionWindow: 45 def test_initial_window(self): 46 from i2p_streaming.scheduler import CongestionWindow 47 cw = CongestionWindow(initial_size=6) 48 assert cw.size == 6 49 50 def test_slow_start_increase(self): 51 from i2p_streaming.scheduler import CongestionWindow 52 cw = CongestionWindow(initial_size=1, ssthresh=16) 53 cw.on_ack() 54 assert cw.size == 2 # Doubles in slow start 55 56 def test_congestion_avoidance(self): 57 from i2p_streaming.scheduler import CongestionWindow 58 cw = CongestionWindow(initial_size=16, ssthresh=16) 59 cw.on_ack() 60 # In congestion avoidance, increase is additive (~1/size per ACK) 61 assert cw.size > 16 62 assert cw.size <= 17 63 64 def test_on_loss(self): 65 from i2p_streaming.scheduler import CongestionWindow 66 cw = CongestionWindow(initial_size=20, ssthresh=32) 67 cw.on_loss() 68 # AIMD: halve the window 69 assert cw.size == 10 70 assert cw.ssthresh == 10 71 72 def test_minimum_window(self): 73 from i2p_streaming.scheduler import CongestionWindow 74 cw = CongestionWindow(initial_size=1, ssthresh=16) 75 cw.on_loss() 76 assert cw.size >= 1 # Never go below 1 77 78 def test_max_window(self): 79 from i2p_streaming.scheduler import CongestionWindow 80 cw = CongestionWindow(initial_size=1, ssthresh=16, max_size=128) 81 for _ in range(200): 82 cw.on_ack() 83 assert cw.size <= 128 84 85 86class TestPacketScheduler: 87 def test_can_send_within_window(self): 88 from i2p_streaming.scheduler import PacketScheduler 89 sched = PacketScheduler(window_size=10) 90 assert sched.can_send() 91 92 def test_cannot_send_window_full(self): 93 from i2p_streaming.scheduler import PacketScheduler 94 sched = PacketScheduler(window_size=2) 95 sched.on_packet_sent(seq=0) 96 sched.on_packet_sent(seq=1) 97 assert not sched.can_send() 98 99 def test_ack_frees_window(self): 100 from i2p_streaming.scheduler import PacketScheduler 101 sched = PacketScheduler(window_size=1) 102 sched.on_packet_sent(seq=0) 103 assert not sched.can_send() 104 sched.on_ack(seq=0) 105 assert sched.can_send() 106 107 def test_outstanding_count(self): 108 from i2p_streaming.scheduler import PacketScheduler 109 sched = PacketScheduler(window_size=10) 110 sched.on_packet_sent(seq=0) 111 sched.on_packet_sent(seq=1) 112 assert sched.outstanding == 2 113 sched.on_ack(seq=0) 114 assert sched.outstanding == 1