diff --git a/test/functional/example_test.py b/test/functional/example_test.py --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -224,8 +224,8 @@ self.log.info("Check that each block was received only once") # The network thread uses a global lock on data access to the P2PConnection objects when sending and receiving # messages. The test thread should acquire the global lock before accessing any P2PConnection data to avoid locking - # and synchronization issues. Note wait_until() acquires this global - # lock when testing the predicate. + # and synchronization issues. Note p2p.wait_until() acquires this + # global lock internally when testing the predicate. with p2p_lock: for block in self.nodes[2].p2p.block_receive_map.values(): assert_equal(block, 1) diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -13,7 +13,6 @@ connect_nodes, disconnect_nodes, hex_str_to_bytes, - wait_until, ) FORK_WARNING_MESSAGE = "Warning: Large-work fork detected, forking after block {}" @@ -179,7 +178,8 @@ self.nodes[0].invalidateblock(invalid_block) # Give bitcoind 10 seconds to write the alert notification - wait_until(lambda: len(os.listdir(self.alertnotify_dir)), timeout=10) + self.wait_until(lambda: len(os.listdir(self.alertnotify_dir)), + timeout=10) # The notification command is unable to properly handle the spaces on # windows. Skip the content check in this case. diff --git a/test/functional/p2p_inv_download.py b/test/functional/p2p_inv_download.py --- a/test/functional/p2p_inv_download.py +++ b/test/functional/p2p_inv_download.py @@ -29,7 +29,6 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, - wait_until, ) from test_framework.wallet_util import bytes_to_wif @@ -156,8 +155,8 @@ while outstanding_peer_index: node_0_mocktime += context.constants.max_getdata_inbound_wait self.nodes[0].setmocktime(node_0_mocktime) - wait_until(lambda: any(getdata_found(i) - for i in outstanding_peer_index)) + self.wait_until(lambda: any(getdata_found(i) + for i in outstanding_peer_index)) for i in outstanding_peer_index: if getdata_found(i): outstanding_peer_index.remove(i) diff --git a/test/functional/test_framework/avatools.py b/test/functional/test_framework/avatools.py --- a/test/functional/test_framework/avatools.py +++ b/test/functional/test_framework/avatools.py @@ -30,7 +30,7 @@ from .util import ( assert_equal, satoshi_round, - wait_until, + wait_until_helper, ) from .wallet_util import bytes_to_wif @@ -153,7 +153,7 @@ return True except JSONRPCException: return False - wait_until(proof_found, timeout=timeout) + wait_until_helper(proof_found, timeout=timeout) if expect_orphan is not None: assert_equal(expect_orphan, wait_for_proof.is_orphan) @@ -204,10 +204,9 @@ self.send_message(msg) def wait_for_avaresponse(self, timeout=5): - wait_until( + self.wait_until( lambda: len(self.avaresponses) > 0, - timeout=timeout, - lock=p2p_lock) + timeout=timeout) with p2p_lock: return self.avaresponses.pop(0) @@ -225,10 +224,9 @@ return self.avapolls.pop(0) if len(self.avapolls) > 0 else None def wait_for_avahello(self, timeout=5): - wait_until( + self.wait_until( lambda: self.avahello is not None, - timeout=timeout, - lock=p2p_lock) + timeout=timeout) with p2p_lock: return self.avahello diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py --- a/test/functional/test_framework/p2p.py +++ b/test/functional/test_framework/p2p.py @@ -72,7 +72,7 @@ NODE_NETWORK, sha256, ) -from test_framework.util import wait_until +from test_framework.util import wait_until_helper logger = logging.getLogger("TestFramework.p2p") @@ -334,7 +334,7 @@ # Track the most recent message of each type. # To wait for a message to be received, pop that message from - # this and use wait_until. + # this and use self.wait_until. self.last_message = {} # A count of the number of ping messages we've sent to the node @@ -481,8 +481,8 @@ assert self.is_connected return test_function_in() - wait_until(test_function, timeout=timeout, lock=p2p_lock, - timeout_factor=self.timeout_factor) + wait_until_helper(test_function, timeout=timeout, lock=p2p_lock, + timeout_factor=self.timeout_factor) def wait_for_disconnect(self, timeout=60): def test_function(): return not self.is_connected @@ -611,8 +611,8 @@ """Close the connections and network event loop.""" self.network_event_loop.call_soon_threadsafe( self.network_event_loop.stop) - wait_until(lambda: not self.network_event_loop.is_running(), - timeout=timeout) + wait_until_helper(lambda: not self.network_event_loop.is_running(), + timeout=timeout) self.network_event_loop.close() self.join(timeout) # Safe to remove event loop. diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -33,7 +33,7 @@ p2p_port, PortSeed, rpc_port, - wait_until, + wait_until_helper, ) @@ -610,8 +610,8 @@ self.sync_mempools(nodes) def wait_until(self, test_function, timeout=60, lock=None): - return wait_until(test_function, timeout=timeout, lock=lock, - timeout_factor=self.options.timeout_factor) + return wait_until_helper(test_function, timeout=timeout, lock=lock, + timeout_factor=self.options.timeout_factor) # Private helper methods. These should not be accessed by the subclass # test scripts. diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -32,7 +32,7 @@ get_rpc_proxy, p2p_port, rpc_url, - wait_until, + wait_until_helper, EncodeDecimal, ) @@ -310,7 +310,8 @@ rpc.getblockcount() # If the call to getblockcount() succeeds then the RPC # connection is up - wait_until(lambda: rpc.getmempoolinfo()['loaded']) + wait_until_helper(lambda: rpc.getmempoolinfo()['loaded'], + timeout_factor=self.timeout_factor) # Wait for the node to finish reindex, block import, and # loading the mempool. Usually importing happens fast or # even "immediate" when the node is started. However, there @@ -456,7 +457,7 @@ return True def wait_until_stopped(self, timeout=BITCOIND_PROC_WAIT_TIMEOUT): - wait_until( + wait_until_helper( self.is_node_stopped, timeout=timeout, timeout_factor=self.timeout_factor) @@ -719,7 +720,8 @@ for p in self.p2ps: p.peer_disconnect() del self.p2ps[:] - wait_until(lambda: self.num_test_p2p_connections() == 0) + wait_until_helper(lambda: self.num_test_p2p_connections() == 0, + timeout_factor=self.timeout_factor) class TestNodeCLIAttr: diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -249,15 +249,15 @@ return Decimal(amount).quantize(Decimal('0.01'), rounding=ROUND_DOWN) -def wait_until(predicate, *, attempts=float('inf'), - timeout=float('inf'), lock=None, timeout_factor=1.0): +def wait_until_helper(predicate, *, attempts=float('inf'), + timeout=float('inf'), lock=None, timeout_factor=1.0): """Sleep until the predicate resolves to be True. Warning: Note that this method is not recommended to be used in tests as it is - not aware of the context of the test framework. Using `wait_until()` counterpart - from `BitcoinTestFramework` or `P2PInterface` class ensures an understandable - amount of timeout and a common shared timeout_factor. Furthermore, `wait_until()` - from `P2PInterface` class in `mininode.py` has a preset lock. + not aware of the context of the test framework. Using the `wait_until()` members + from `BitcoinTestFramework` or `P2PInterface` class ensures the timeout is + properly scaled. Furthermore, `wait_until()` from `P2PInterface` class in + `p2p.py` has a preset lock. """ if attempts == float('inf') and timeout == float('inf'): timeout = 60 @@ -453,7 +453,7 @@ raise # wait to disconnect - wait_until(lambda: not get_peer_ids(), timeout=5) + wait_until_helper(lambda: not get_peer_ids(), timeout=5) def connect_nodes(from_node, to_node): @@ -467,14 +467,12 @@ # See comments in net_processing: # * Must have a version message before anything else # * Must have a verack message before anything else - wait_until( - lambda: all( - peer['version'] != 0 for peer in from_node.getpeerinfo())) - wait_until( - lambda: all( - peer['bytesrecv_per_msg'].pop( - 'verack', - 0) == 24 for peer in from_node.getpeerinfo())) + wait_until_helper( + lambda: all(peer['version'] != 0 + for peer in from_node.getpeerinfo())) + wait_until_helper( + lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 + for peer in from_node.getpeerinfo())) # Transaction/Block functions