A Python port of the Invisible Internet Project (I2P)
1"""Tests for Lease2 (LS2 format with 4-byte second timestamps)."""
2
3import struct
4import time
5
6from i2p_data.lease import Lease2
7
8
9def test_lease2_size_is_40():
10 assert Lease2.SIZE == 40
11
12
13def test_lease2_roundtrip():
14 gw = b"\x01" * 32
15 tid = 12345
16 end_ms = int(time.time() * 1000) + 600_000 # 10 min from now
17 lease = Lease2(gw, tid, end_ms)
18 data = lease.to_bytes()
19 assert len(data) == 40
20 restored = Lease2.from_bytes(data)
21 assert restored.gateway_hash == gw
22 assert restored.tunnel_id == tid
23 # Roundtrip loses sub-second precision (ms → sec → ms)
24 assert abs(restored.end_date - end_ms) < 1000
25
26
27def test_lease2_timestamp_conversion():
28 """Wire format uses seconds, internal uses milliseconds."""
29 gw = b"\xab" * 32
30 end_sec = 1700000000
31 end_ms = end_sec * 1000
32 lease = Lease2(gw, 1, end_ms)
33 data = lease.to_bytes()
34 # Last 4 bytes should be the seconds value
35 wire_sec = struct.unpack("!I", data[36:40])[0]
36 assert wire_sec == end_sec
37
38
39def test_lease2_is_expired():
40 gw = b"\x00" * 32
41 past_ms = int(time.time() * 1000) - 60_000
42 lease = Lease2(gw, 1, past_ms)
43 assert lease.is_expired()
44
45 future_ms = int(time.time() * 1000) + 600_000
46 lease2 = Lease2(gw, 1, future_ms)
47 assert not lease2.is_expired()
48
49
50def test_lease2_from_bytes_too_short():
51 import pytest
52 with pytest.raises(ValueError, match="Lease2 requires 40 bytes"):
53 Lease2.from_bytes(b"\x00" * 39)