Skip to content

Commit 017e1ae

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

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

tests/test_connection.py

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

0 commit comments

Comments
 (0)