Skip to content

Commit b14446b

Browse files
committed
pytest: ... start testing
1 parent 5eab8db commit b14446b

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

tests/test_connection.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,167 @@ def test_connect_basic(node_factory):
6969
assert l1.rpc.listpeers(l2id)['peers'][0]['num_channels'] == 2
7070

7171

72+
# Helper function to setup nodes with the specified test case
73+
def alt_addr_setup_nodes(node_factory, test_case):
74+
alt_addr = "127.0.0.1"
75+
alt_port = node_factory.get_unused_port()
76+
77+
opts = {
78+
'may_reconnect': True,
79+
'dev-no-reconnect': None,
80+
}
81+
alt_port2 = None
82+
83+
if test_case == "standard":
84+
opts['alt-addr'] = f'{alt_addr}:{alt_port}'
85+
elif test_case == "rpc":
86+
alt_port2 = node_factory.get_unused_port()
87+
opts['alt-bind-addr'] = [f'{alt_addr}:{alt_port}', f'{alt_addr}:{alt_port2}']
88+
elif test_case == "announce":
89+
opts['alt-bind-addr'] = f'{alt_addr}:{alt_port}'
90+
opts['alt-announce-addr'] = f'{alt_addr}:{alt_port}'
91+
elif test_case == "whitelist":
92+
opts['alt-bind-addr'] = f'{alt_addr}:{alt_port}'
93+
elif test_case == "clear_alt_addr":
94+
opts['alt-addr'] = f'{alt_addr}:{alt_port}'
95+
else:
96+
raise ValueError("Unknown test case")
97+
98+
l1, l2 = node_factory.line_graph(2, fundchannel=True, opts=[{'may_reconnect': True}, opts])
99+
100+
return l1, l2, alt_addr, alt_port, alt_port2
101+
102+
103+
@pytest.mark.parametrize("test_case", [
104+
"standard",
105+
"rpc",
106+
"announce"
107+
])
108+
def test_alt_addr_connection_scenarios(node_factory, bitcoind, test_case):
109+
"""Test various alternate connection address scenarios for nodes."""
110+
111+
# Function to verify that the node is correctly bound to the alternate address
112+
def verify_binding(l2, alt_addr, alt_port):
113+
binding = l2.rpc.getinfo()['binding']
114+
assert len(binding) > 0, "No binding found for l2"
115+
assert any(bind['address'] == alt_addr for bind in binding), f"Expected alt-addr {alt_addr}, found {binding}"
116+
assert any(bind['port'] == alt_port for bind in binding), f"Expected alt-port {alt_port}, found {binding}"
117+
118+
# Function to reconnect the node using the alternate address and verify the connection
119+
def reconnect_and_verify(l1, l2, alt_addr, alt_port):
120+
l1.rpc.disconnect(l2.info['id'], force=True)
121+
assert not any(peer['connected'] for peer in l1.rpc.listpeers()['peers']), "l1 should not have any connected peers"
122+
123+
l1.rpc.connect(l2.info['id'], alt_addr, alt_port)
124+
wait_for(lambda: l1.rpc.listpeers(l2.info['id'])['peers'][0]['connected'], timeout=180)
125+
126+
connected_peer = l1.rpc.getpeer(l2.info['id'])
127+
assert connected_peer['connected'], "Peers not connected"
128+
assert connected_peer['netaddr'][0] == f'{alt_addr}:{alt_port}', f"Connection not using alt-addr: {connected_peer['netaddr'][0]}"
129+
130+
def auto_reconnect_and_verify(l1, l2, alt_addr, alt_port):
131+
l2.rpc.disconnect(l1.info['id'], force=True)
132+
assert not any(peer['connected'] for peer in l2.rpc.listpeers()['peers']), "l2 should not have any connected peers"
133+
134+
# Wait for l1 to auto-reconnect
135+
wait_for(lambda: any(peer['connected'] for peer in l1.rpc.listpeers()['peers']), timeout=180)
136+
137+
# Verify that l1 reconnected using alt-addr
138+
connected_peer = l1.rpc.getpeer(l2.info['id'])
139+
assert connected_peer['connected'], "Peers not reconnected"
140+
assert connected_peer['netaddr'][0] == f'{alt_addr}:{alt_port}', "Connection not using alt-addr"
141+
142+
# Function to restart the node and verify it reconnects using the alternate address
143+
def restart_and_verify(l1, l2, alt_addr, alt_port):
144+
l2.restart()
145+
wait_for(lambda: any(peer['connected'] for peer in l1.rpc.listpeers()['peers']), timeout=180)
146+
147+
connected_peer = l1.rpc.getpeer(l2.info['id'])
148+
assert connected_peer['connected'], "Peers not connected"
149+
assert connected_peer['netaddr'][0] == f'{alt_addr}:{alt_port}', "Connection address does not match"
150+
151+
# l2 provides alt_addrs to l1, l1 connects to l2.
152+
l1, l2, alt_addr, alt_port, alt_port2 = alt_addr_setup_nodes(node_factory, test_case)
153+
154+
if test_case == "rpc":
155+
# Test with two alternate addresses in one RPC call
156+
l2.rpc.alt_addr(l1.info['id'], [f'{alt_addr}:{alt_port}', f'{alt_addr}:{alt_port2}'])
157+
verify_binding(l2, alt_addr, alt_port)
158+
verify_binding(l2, alt_addr, alt_port2)
159+
160+
reconnect_and_verify(l1, l2, alt_addr, alt_port)
161+
auto_reconnect_and_verify(l1, l2, alt_addr, alt_port)
162+
restart_and_verify(l1, l2, alt_addr, alt_port)
163+
164+
# Test with the second alternate address
165+
reconnect_and_verify(l1, l2, alt_addr, alt_port2)
166+
auto_reconnect_and_verify(l1, l2, alt_addr, alt_port2)
167+
restart_and_verify(l1, l2, alt_addr, alt_port2)
168+
169+
# Test to clear the alt-addrs and connect to default
170+
l2.rpc.alt_addr(l1.info['id'], [f''])
171+
default_addr = l2.rpc.getinfo()['binding'][0]['address']
172+
default_port = l2.rpc.getinfo()['binding'][0]['port']
173+
reconnect_and_verify(l1, l2, default_addr, default_port)
174+
175+
else:
176+
verify_binding(l2, alt_addr, alt_port)
177+
reconnect_and_verify(l1, l2, alt_addr, alt_port)
178+
auto_reconnect_and_verify(l1, l2, alt_addr, alt_port)
179+
restart_and_verify(l1, l2, alt_addr, alt_port)
180+
181+
182+
@pytest.mark.parametrize("test_case", [
183+
("wrong_port_standard"),
184+
("wrong_port_rpc"),
185+
])
186+
def test_alt_addr_wrong_port_handling(node_factory, test_case):
187+
"""Test handling of incorrect ports with alternative addresses."""
188+
189+
l1, l2, alt_addr, alt_port, alt_port2 = alt_addr_setup_nodes(node_factory, test_case.replace("wrong_port_", ""))
190+
191+
wrong_port = node_factory.get_unused_port()
192+
193+
if "rpc" in test_case:
194+
l2.rpc.alt_addr(l1.info['id'], [f'{alt_addr}:{wrong_port}'])
195+
196+
l1.rpc.disconnect(l2.info['id'], force=True)
197+
assert not any(peer['connected'] for peer in l1.rpc.listpeers()['peers']), "l1 should not have any connected peers"
198+
assert not any(peer['connected'] for peer in l2.rpc.listpeers()['peers']), "l2 should not have any connected peers"
199+
200+
with pytest.raises(Exception):
201+
l1.rpc.connect(l2.info['id'], alt_addr, wrong_port)
202+
connected_peer = l1.rpc.listpeers(l2.info['id'])['peers']
203+
assert len(connected_peer) == 0 or not connected_peer[0]['connected'], "Peer should not be connected using wrong_port"
204+
205+
l1.restart()
206+
connected_peer = l1.rpc.listpeers(l2.info['id'])['peers']
207+
assert len(connected_peer) == 0 or not connected_peer[0]['connected'], "Peer should not be connected using wrong_port"
208+
else:
209+
l1.rpc.connect(l2.info['id'], alt_addr, wrong_port)
210+
connected_peer = l1.rpc.getpeer(l2.info['id'])
211+
assert not connected_peer['netaddr'][0] == f'{alt_addr}:{wrong_port}', "Connection address does not match"
212+
213+
214+
def test_alt_addr_whitelist_handling(node_factory):
215+
"""Test handling of whitelist with alternate addresses."""
216+
217+
l1, l2, alt_addr, alt_port, alt_port2 = alt_addr_setup_nodes(node_factory, "whitelist")
218+
l3 = node_factory.get_node()
219+
220+
try:
221+
l3.rpc.connect(l2.info['id'], alt_addr, alt_port)
222+
except RpcError as e:
223+
print(f"RPC Error: {e.error}")
224+
assert e.error['code'] == 401, f"Unexpected error code: {e.error['code']}"
225+
assert "peer closed connection" in e.error['message'], f"Unexpected error message: {e.error['message']}"
226+
227+
l2.daemon.wait_for_log(f"Connection attempt from address {alt_addr}:{alt_port} which is not in the whitelist. Closing connection.")
228+
229+
connected_peers = l2.rpc.listpeers()['peers']
230+
assert not any(peer['id'] == l3.info['id'] and peer['connected'] for peer in connected_peers), "l3 should not be connected to l2"
231+
232+
72233
def test_remote_addr(node_factory, bitcoind):
73234
"""Check address discovery (BOLT1 #917) init remote_addr works as designed:
74235

0 commit comments

Comments
 (0)