diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py --- a/test/functional/feature_loadblock.py +++ b/test/functional/feature_loadblock.py @@ -16,10 +16,8 @@ import tempfile import urllib -from test_framework.test_framework import ( - BitcoinTestFramework, -) -from test_framework.util import assert_equal, wait_until +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal class LoadblockTest(BitcoinTestFramework): @@ -76,7 +74,8 @@ self.log.info("Restart second, unsynced node with bootstrap file") self.stop_node(1) self.start_node(1, ["-loadblock=" + bootstrap_file]) - wait_until(lambda: self.nodes[1].getblockcount() == 100) + # start_node is blocking on all block files being imported + assert_equal(self.nodes[1].getblockcount(), 100) assert_equal(self.nodes[1].getblockchaininfo()['blocks'], 100) assert_equal( diff --git a/test/functional/feature_reindex.py b/test/functional/feature_reindex.py --- a/test/functional/feature_reindex.py +++ b/test/functional/feature_reindex.py @@ -10,7 +10,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import wait_until +from test_framework.util import assert_equal class ReindexTest(BitcoinTestFramework): @@ -27,7 +27,8 @@ extra_args = [ ["-reindex-chainstate" if justchainstate else "-reindex"]] self.start_nodes(extra_args) - wait_until(lambda: self.nodes[0].getblockcount() == blockcount) + # start_node is blocking on reindex + assert_equal(self.nodes[0].getblockcount(), blockcount) self.log.info("Success") def run_test(self): diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -44,7 +44,6 @@ assert_equal, assert_greater_than_or_equal, assert_raises_rpc_error, - wait_until, ) @@ -94,8 +93,9 @@ self.start_node(1, extra_args=["-persistmempool=0"]) self.start_node(0) self.start_node(2) - wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"], timeout=1) - wait_until(lambda: self.nodes[2].getmempoolinfo()["loaded"], timeout=1) + # start_node is blocking on the mempool being loaded + assert self.nodes[0].getmempoolinfo()["loaded"] + assert self.nodes[2].getmempoolinfo()["loaded"] assert_equal(len(self.nodes[0].getrawmempool()), 5) assert_equal(len(self.nodes[2].getrawmempool()), 5) # The others have loaded their mempool. If node_1 loaded anything, we'd @@ -121,14 +121,14 @@ "Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") self.stop_nodes() self.start_node(0, extra_args=["-persistmempool=0"]) - wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"]) + assert self.nodes[0].getmempoolinfo()["loaded"] assert_equal(len(self.nodes[0].getrawmempool()), 0) self.log.debug( "Stop-start node0. Verify that it has the transactions in its mempool.") self.stop_nodes() self.start_node(0) - wait_until(lambda: self.nodes[0].getmempoolinfo()["loaded"]) + assert self.nodes[0].getmempoolinfo()["loaded"] assert_equal(len(self.nodes[0].getrawmempool()), 5) mempooldat0 = os.path.join( @@ -146,7 +146,7 @@ os.rename(mempooldat0, mempooldat1) self.stop_nodes() self.start_node(1, extra_args=[]) - wait_until(lambda: self.nodes[1].getmempoolinfo()["loaded"]) + assert self.nodes[1].getmempoolinfo()["loaded"] assert_equal(len(self.nodes[1].getrawmempool()), 5) self.log.debug( 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 @@ -303,6 +303,25 @@ rpc.getblockcount() # If the call to getblockcount() succeeds then the RPC # connection is up + wait_until(lambda: rpc.getmempoolinfo()['loaded']) + # 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 + # is no guarantee and sometimes ThreadImport might finish + # later. This is going to cause intermittent test failures, + # because generally the tests assume the node is fully + # ready after being started. + # + # For example, the node will reject block messages from p2p + # when it is still importing with the error "Unexpected + # block message received" + # + # The wait is done here to make tests as robust as possible + # and prevent racy tests and intermittent failures as much + # as possible. Some tests might not need this, but the + # overhead is trivial, and the added gurantees are worth + # the minimal performance cost. + self.log.debug("RPC successfully started") if self.use_cli: return diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py --- a/test/functional/wallet_abandonconflict.py +++ b/test/functional/wallet_abandonconflict.py @@ -19,7 +19,6 @@ connect_nodes, disconnect_nodes, satoshi_round, - wait_until, ) @@ -126,7 +125,7 @@ # TODO: redo with eviction self.stop_node(0) self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) - wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded']) + assert self.nodes[0].getmempoolinfo()['loaded'] # Verify txs no longer in either node's mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) @@ -160,7 +159,7 @@ # from wallet on startup once abandoned. self.stop_node(0) self.start_node(0, extra_args=["-minrelaytxfee=0.00001"]) - wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded']) + assert self.nodes[0].getmempoolinfo()['loaded'] assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(self.nodes[0].getbalance(), balance) @@ -185,7 +184,7 @@ # Reset to a higher relay fee so that we abandon a transaction self.stop_node(0) self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) - wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded']) + assert self.nodes[0].getmempoolinfo()['loaded'] assert_equal(len(self.nodes[0].getrawmempool()), 0) newbalance = self.nodes[0].getbalance() assert_equal(newbalance, balance - Decimal("24.9996")) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -4,7 +4,6 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the wallet.""" from decimal import Decimal -import time from test_framework.messages import FromHex, CTransaction from test_framework.test_framework import BitcoinTestFramework @@ -552,13 +551,11 @@ self.extra_args[0] + ["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]) - # wait for loadmempool - timeout = 10 - while (timeout > 0 and len( - self.nodes[0].getrawmempool()) < chainlimit * 2): - time.sleep(0.5) - timeout -= 0.5 - assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2) + # wait until the wallet has submitted all transactions to the mempool + wait_until( + lambda: len( + self.nodes[0].getrawmempool()) == chainlimit * + 2) node0_balance = self.nodes[0].getbalance() # With walletrejectlongchains we will not create the tx and store it in