Skip to content

Commit 3c93623

Browse files
author
MarcoFalke
committed
Merge #19489: test: Fail wait_until early if connection is lost
faa9a74 test: Fail wait_until early if connection is lost (MarcoFalke) Pull request description: Calling `minonode.wait_until` needs a connection to make progress (e.g. waiting for an inv), unless the mininode waits for the initial connection or for a disconnection. So for test development and failure debugging, fail early in all `wait_until`, unless opted out. ACKs for top commit: jnewbery: Code review ACK faa9a74. Tree-SHA512: 4be850b96e23b87bc2ff42c028a5045d6f5cdbc9482ce6a6ba01cc5eb26710dab9e2ed547c363aac4bd5825151ee9996fb797261420b631bceeddbfa698d1dec
2 parents bb2a9f9 + faa9a74 commit 3c93623

File tree

3 files changed

+27
-29
lines changed

3 files changed

+27
-29
lines changed

test/functional/p2p_filter.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,11 @@ def run_test(self):
218218
# Add peer but do not send version yet
219219
filter_peer_without_nrelay = self.nodes[0].add_p2p_connection(P2PBloomFilter(), send_version=False, wait_for_verack=False)
220220
# Send version with fRelay=False
221-
filter_peer_without_nrelay.wait_until(lambda: filter_peer_without_nrelay.is_connected, timeout=10)
221+
filter_peer_without_nrelay.wait_until(
222+
lambda: filter_peer_without_nrelay.is_connected,
223+
timeout=10,
224+
check_connected=False,
225+
)
222226
version_without_fRelay = msg_version()
223227
version_without_fRelay.nRelay = 0
224228
filter_peer_without_nrelay.send_message(version_without_fRelay)

test/functional/p2p_ping.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,8 @@
77

88
import time
99

10-
from test_framework.messages import (
11-
msg_pong,
12-
)
13-
from test_framework.mininode import (
14-
P2PInterface,
15-
wait_until,
16-
)
10+
from test_framework.messages import msg_pong
11+
from test_framework.mininode import P2PInterface
1712
from test_framework.test_framework import BitcoinTestFramework
1813
from test_framework.util import assert_equal
1914

@@ -78,7 +73,7 @@ def run_test(self):
7873
with self.nodes[0].assert_debug_log(['pong peer=0: Nonce mismatch']):
7974
# mock time PING_INTERVAL ahead to trigger node into sending a ping
8075
self.mock_forward(PING_INTERVAL + 1)
81-
wait_until(lambda: 'ping' in no_pong_node.last_message)
76+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
8277
self.mock_forward(9)
8378
# Send the wrong pong
8479
no_pong_node.send_and_ping(msg_pong(no_pong_node.last_message.pop('ping').nonce - 1))
@@ -93,27 +88,27 @@ def run_test(self):
9388
assert 'ping' not in no_pong_node.last_message
9489
# mock time PING_INTERVAL ahead to trigger node into sending a ping
9590
self.mock_forward(PING_INTERVAL + 1)
96-
wait_until(lambda: 'ping' in no_pong_node.last_message)
91+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
9792
ping_delay = 29
9893
self.mock_forward(ping_delay)
99-
wait_until(lambda: 'ping' in no_pong_node.last_message)
94+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
10095
no_pong_node.send_and_ping(msg_pong(no_pong_node.last_message.pop('ping').nonce))
10196
self.check_peer_info(pingtime=ping_delay, minping=ping_delay, pingwait=None)
10297

10398
self.log.info('Check that minping is decreased after a fast roundtrip')
10499
# mock time PING_INTERVAL ahead to trigger node into sending a ping
105100
self.mock_forward(PING_INTERVAL + 1)
106-
wait_until(lambda: 'ping' in no_pong_node.last_message)
101+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
107102
ping_delay = 9
108103
self.mock_forward(ping_delay)
109-
wait_until(lambda: 'ping' in no_pong_node.last_message)
104+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
110105
no_pong_node.send_and_ping(msg_pong(no_pong_node.last_message.pop('ping').nonce))
111106
self.check_peer_info(pingtime=ping_delay, minping=ping_delay, pingwait=None)
112107

113108
self.log.info('Check that peer is disconnected after ping timeout')
114109
assert 'ping' not in no_pong_node.last_message
115110
self.nodes[0].ping()
116-
wait_until(lambda: 'ping' in no_pong_node.last_message)
111+
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message)
117112
with self.nodes[0].assert_debug_log(['ping timeout: 1201.000000s']):
118113
self.mock_forward(20 * 60 + 1)
119114
time.sleep(4) # peertimeout + 1

test/functional/test_framework/mininode.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -388,18 +388,22 @@ def on_version(self, message):
388388

389389
# Connection helper methods
390390

391-
def wait_until(self, test_function, timeout=60):
391+
def wait_until(self, test_function_in, *, timeout=60, check_connected=True):
392+
def test_function():
393+
if check_connected:
394+
assert self.is_connected
395+
return test_function_in()
396+
392397
wait_until(test_function, timeout=timeout, lock=mininode_lock, timeout_factor=self.timeout_factor)
393398

394399
def wait_for_disconnect(self, timeout=60):
395400
test_function = lambda: not self.is_connected
396-
self.wait_until(test_function, timeout=timeout)
401+
self.wait_until(test_function, timeout=timeout, check_connected=False)
397402

398403
# Message receiving helper methods
399404

400405
def wait_for_tx(self, txid, timeout=60):
401406
def test_function():
402-
assert self.is_connected
403407
if not self.last_message.get('tx'):
404408
return False
405409
return self.last_message['tx'].tx.rehash() == txid
@@ -408,14 +412,12 @@ def test_function():
408412

409413
def wait_for_block(self, blockhash, timeout=60):
410414
def test_function():
411-
assert self.is_connected
412415
return self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash
413416

414417
self.wait_until(test_function, timeout=timeout)
415418

416419
def wait_for_header(self, blockhash, timeout=60):
417420
def test_function():
418-
assert self.is_connected
419421
last_headers = self.last_message.get('headers')
420422
if not last_headers:
421423
return False
@@ -425,7 +427,6 @@ def test_function():
425427

426428
def wait_for_merkleblock(self, blockhash, timeout=60):
427429
def test_function():
428-
assert self.is_connected
429430
last_filtered_block = self.last_message.get('merkleblock')
430431
if not last_filtered_block:
431432
return False
@@ -437,9 +438,7 @@ def wait_for_getdata(self, hash_list, timeout=60):
437438
"""Waits for a getdata message.
438439
439440
The object hashes in the inventory vector must match the provided hash_list."""
440-
441441
def test_function():
442-
assert self.is_connected
443442
last_data = self.last_message.get("getdata")
444443
if not last_data:
445444
return False
@@ -454,9 +453,7 @@ def wait_for_getheaders(self, timeout=60):
454453
value must be explicitly cleared before calling this method, or this will return
455454
immediately with success. TODO: change this method to take a hash value and only
456455
return true if the correct block header has been requested."""
457-
458456
def test_function():
459-
assert self.is_connected
460457
return self.last_message.get("getheaders")
461458

462459
self.wait_until(test_function, timeout=timeout)
@@ -467,7 +464,6 @@ def wait_for_inv(self, expected_inv, timeout=60):
467464
raise NotImplementedError("wait_for_inv() will only verify the first inv object")
468465

469466
def test_function():
470-
assert self.is_connected
471467
return self.last_message.get("inv") and \
472468
self.last_message["inv"].inv[0].type == expected_inv[0].type and \
473469
self.last_message["inv"].inv[0].hash == expected_inv[0].hash
@@ -478,7 +474,7 @@ def wait_for_verack(self, timeout=60):
478474
def test_function():
479475
return "verack" in self.last_message
480476

481-
self.wait_until(test_function, timeout=timeout)
477+
self.wait_until(test_function, timeout=timeout, check_connected=False)
482478

483479
# Message sending helper functions
484480

@@ -491,7 +487,6 @@ def sync_with_ping(self, timeout=60):
491487
self.send_message(msg_ping(nonce=self.ping_counter))
492488

493489
def test_function():
494-
assert self.is_connected
495490
return self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter
496491

497492
self.wait_until(test_function, timeout=timeout)
@@ -609,7 +604,11 @@ def send_blocks_and_test(self, blocks, node, *, success=True, force_send=False,
609604
self.send_message(msg_block(block=b))
610605
else:
611606
self.send_message(msg_headers([CBlockHeader(block) for block in blocks]))
612-
self.wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout)
607+
self.wait_until(
608+
lambda: blocks[-1].sha256 in self.getdata_requests,
609+
timeout=timeout,
610+
check_connected=success,
611+
)
613612

614613
if expect_disconnect:
615614
self.wait_for_disconnect(timeout=timeout)
@@ -677,6 +676,6 @@ def wait_for_broadcast(self, txns, timeout=60):
677676
The mempool should mark unbroadcast=False for these transactions.
678677
"""
679678
# Wait until invs have been received (and getdatas sent) for each txid.
680-
self.wait_until(lambda: set(self.tx_invs_received.keys()) == set([int(tx, 16) for tx in txns]), timeout)
679+
self.wait_until(lambda: set(self.tx_invs_received.keys()) == set([int(tx, 16) for tx in txns]), timeout=timeout)
681680
# Flush messages and wait for the getdatas to be processed
682681
self.sync_with_ping()

0 commit comments

Comments
 (0)