diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/p2p_dos_header_tree.py | 9 | ||||
-rwxr-xr-x | test/functional/p2p_filter.py | 8 | ||||
-rwxr-xr-x | test/functional/p2p_invalid_messages.py | 1 | ||||
-rwxr-xr-x | test/functional/p2p_leak.py | 8 | ||||
-rwxr-xr-x | test/functional/p2p_timeouts.py | 9 | ||||
-rwxr-xr-x | test/functional/test_framework/messages.py | 17 | ||||
-rwxr-xr-x | test/functional/test_framework/mininode.py | 3 | ||||
-rwxr-xr-x | test/functional/test_framework/test_node.py | 15 | ||||
-rw-r--r-- | test/functional/test_framework/util.py | 6 | ||||
-rwxr-xr-x | test/functional/wallet_listsinceblock.py | 20 | ||||
-rw-r--r-- | test/sanitizer_suppressions/tsan | 8 |
11 files changed, 76 insertions, 28 deletions
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py index 6676b84e54..28dd809ca5 100755 --- a/test/functional/p2p_dos_header_tree.py +++ b/test/functional/p2p_dos_header_tree.py @@ -47,8 +47,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): self.log.info("Feed all non-fork headers, including and up to the first checkpoint") self.nodes[0].add_p2p_connection(P2PInterface()) - self.nodes[0].p2p.send_message(msg_headers(self.headers)) - self.nodes[0].p2p.sync_with_ping() + self.nodes[0].p2p.send_and_ping(msg_headers(self.headers)) assert { 'height': 546, 'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70', @@ -65,8 +64,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): # On node 0 it succeeds because checkpoints are disabled self.restart_node(0, extra_args=['-nocheckpoints']) self.nodes[0].add_p2p_connection(P2PInterface()) - self.nodes[0].p2p.send_message(msg_headers(self.headers_fork)) - self.nodes[0].p2p.sync_with_ping() + self.nodes[0].p2p.send_and_ping(msg_headers(self.headers_fork)) assert { "height": 2, "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39", @@ -76,8 +74,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): # On node 1 it succeeds because no checkpoint has been reached yet by a chain tip self.nodes[1].add_p2p_connection(P2PInterface()) - self.nodes[1].p2p.send_message(msg_headers(self.headers_fork)) - self.nodes[1].p2p.sync_with_ping() + self.nodes[1].p2p.send_and_ping(msg_headers(self.headers_fork)) assert { "height": 2, "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39", diff --git a/test/functional/p2p_filter.py b/test/functional/p2p_filter.py index a22ee91483..ad7a9dcf6e 100755 --- a/test/functional/p2p_filter.py +++ b/test/functional/p2p_filter.py @@ -11,6 +11,7 @@ from test_framework.messages import ( MSG_FILTERED_BLOCK, msg_getdata, msg_filterload, + msg_filterclear, ) from test_framework.mininode import ( P2PInterface, @@ -97,6 +98,13 @@ class FilterTest(BitcoinTestFramework): filter_node.wait_for_tx(txid) assert not filter_node.merkleblock_received + self.log.info('Check that after deleting filter all txs get relayed again') + filter_node.send_message(msg_filterclear()) + filter_node.sync_with_ping() + for _ in range(5): + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 7) + filter_node.wait_for_tx(txid) + if __name__ == '__main__': FilterTest().main() diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py index 9876d749ff..759f111e69 100755 --- a/test/functional/p2p_invalid_messages.py +++ b/test/functional/p2p_invalid_messages.py @@ -140,7 +140,6 @@ class InvalidMessagesTest(BitcoinTestFramework): # Node is still up. conn = node.add_p2p_connection(P2PDataStore()) - conn.sync_with_ping() def test_magic_bytes(self): conn = self.nodes[0].add_p2p_connection(P2PDataStore()) diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py index 06049db54c..2751ae6a5b 100755 --- a/test/functional/p2p_leak.py +++ b/test/functional/p2p_leak.py @@ -19,6 +19,7 @@ from test_framework.util import wait_until banscore = 10 + class CLazyNode(P2PInterface): def __init__(self): super().__init__() @@ -88,6 +89,7 @@ class CNodeNoVerackIdle(CLazyNode): self.send_message(msg_ping()) self.send_message(msg_getaddr()) + class P2PLeakTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -96,7 +98,11 @@ class P2PLeakTest(BitcoinTestFramework): def run_test(self): no_version_bannode = self.nodes[0].add_p2p_connection(CNodeNoVersionBan(), send_version=False, wait_for_verack=False) no_version_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVersionIdle(), send_version=False, wait_for_verack=False) - no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle()) + no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle(), wait_for_verack=False) + + # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the + # verack, since we never sent one + no_verack_idlenode.wait_for_verack() wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock) wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock) diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py index 02ceec3dc1..c1235f8a6b 100755 --- a/test/functional/p2p_timeouts.py +++ b/test/functional/p2p_timeouts.py @@ -27,11 +27,13 @@ from test_framework.messages import msg_ping from test_framework.mininode import P2PInterface from test_framework.test_framework import BitcoinTestFramework + class TestP2PConn(P2PInterface): def on_version(self, message): # Don't send a verack in response pass + class TimeoutsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -41,10 +43,14 @@ class TimeoutsTest(BitcoinTestFramework): def run_test(self): # Setup the p2p connections - no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn()) + no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn(), wait_for_verack=False) no_version_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False) no_send_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False) + # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the + # verack, since we never sent one + no_verack_node.wait_for_verack() + sleep(1) assert no_verack_node.is_connected @@ -81,5 +87,6 @@ class TimeoutsTest(BitcoinTestFramework): assert not no_version_node.is_connected assert not no_send_node.is_connected + if __name__ == '__main__': TimeoutsTest().main() diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 9e87ad62a1..ff0c763b72 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -1356,6 +1356,23 @@ class msg_filterload: self.data, self.nHashFuncs, self.nTweak, self.nFlags) +class msg_filterclear: + __slots__ = () + command = b"filterclear" + + def __init__(self): + pass + + def deserialize(self, f): + pass + + def serialize(self): + return b"" + + def __repr__(self): + return "msg_filterclear()" + + class msg_feefilter: __slots__ = ("feerate",) command = b"feefilter" diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index b760e7e1f3..ce51513ce9 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -30,6 +30,7 @@ from test_framework.messages import ( msg_blocktxn, msg_cmpctblock, msg_feefilter, + msg_filterclear, msg_filterload, msg_getaddr, msg_getblocks, @@ -64,6 +65,7 @@ MESSAGEMAP = { b"blocktxn": msg_blocktxn, b"cmpctblock": msg_cmpctblock, b"feefilter": msg_feefilter, + b"filterclear": msg_filterclear, b"filterload": msg_filterload, b"getaddr": msg_getaddr, b"getblocks": msg_getblocks, @@ -322,6 +324,7 @@ class P2PInterface(P2PConnection): def on_blocktxn(self, message): pass def on_cmpctblock(self, message): pass def on_feefilter(self, message): pass + def on_filterclear(self, message): pass def on_filterload(self, message): pass def on_getaddr(self, message): pass def on_getblocks(self, message): pass diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index c7559ac7c8..8260c917fe 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -468,7 +468,19 @@ class TestNode(): p2p_conn.peer_connect(**kwargs, net=self.chain)() self.p2ps.append(p2p_conn) if wait_for_verack: + # Wait for the node to send us the version and verack p2p_conn.wait_for_verack() + # At this point we have sent our version message and received the version and verack, however the full node + # has not yet received the verack from us (in reply to their version). So, the connection is not yet fully + # established (fSuccessfullyConnected). + # + # This shouldn't lead to any issues when sending messages, since the verack will be in-flight before the + # message we send. However, it might lead to races where we are expecting to receive a message. E.g. a + # transaction that will be added to the mempool as soon as we return here. + # + # So syncing here is redundant when we only want to send a message, but the cost is low (a few milliseconds) + # in comparision to the upside of making tests less fragile and unexpected intermittent errors less likely. + p2p_conn.sync_with_ping() return p2p_conn @@ -487,6 +499,7 @@ class TestNode(): p.peer_disconnect() del self.p2ps[:] + class TestNodeCLIAttr: def __init__(self, cli, command): self.cli = cli @@ -498,6 +511,7 @@ class TestNodeCLIAttr: def get_request(self, *args, **kwargs): return lambda: self(*args, **kwargs) + def arg_to_cli(arg): if isinstance(arg, bool): return str(arg).lower() @@ -506,6 +520,7 @@ def arg_to_cli(arg): else: return str(arg) + class TestNodeCLI(): """Interface to bitcoin-cli for an individual node""" diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 5bb73aee7e..e89b4e9879 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -393,6 +393,7 @@ def connect_nodes(from_connection, node_num): # with transaction relaying wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo())) + def sync_blocks(rpc_connections, *, wait=1, timeout=60): """ Wait until everybody has the same tip. @@ -406,9 +407,12 @@ def sync_blocks(rpc_connections, *, wait=1, timeout=60): best_hash = [x.getbestblockhash() for x in rpc_connections] if best_hash.count(best_hash[0]) == len(rpc_connections): return + # Check that each peer has at least one connection + assert (all([len(x.getpeerinfo()) for x in rpc_connections])) time.sleep(wait) raise AssertionError("Block sync timed out:{}".format("".join("\n {!r}".format(b) for b in best_hash))) + def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True): """ Wait until everybody has the same transactions in their memory @@ -422,6 +426,8 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True): for r in rpc_connections: r.syncwithvalidationinterfacequeue() return + # Check that each peer has at least one connection + assert (all([len(x.getpeerinfo()) for x in rpc_connections])) time.sleep(wait) raise AssertionError("Mempool sync timed out:{}".format("".join("\n {!r}".format(m) for m in pool))) diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 229eda9806..6d51ca6c93 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -111,23 +111,21 @@ class ListSinceBlockTest(BitcoinTestFramework): senttx = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1) # generate on both sides - lastblockhash = self.nodes[1].generate(6)[5] - self.nodes[2].generate(7) - self.log.debug('lastblockhash={}'.format(lastblockhash)) + nodes1_last_blockhash = self.nodes[1].generate(6)[-1] + nodes2_first_blockhash = self.nodes[2].generate(7)[0] + self.log.debug("nodes[1] last blockhash = {}".format(nodes1_last_blockhash)) + self.log.debug("nodes[2] first blockhash = {}".format(nodes2_first_blockhash)) self.sync_all(self.nodes[:2]) self.sync_all(self.nodes[2:]) self.join_network() - # listsinceblock(lastblockhash) should now include tx, as seen from nodes[0] - lsbres = self.nodes[0].listsinceblock(lastblockhash) - found = False - for tx in lsbres['transactions']: - if tx['txid'] == senttx: - found = True - break - assert found + # listsinceblock(nodes1_last_blockhash) should now include tx as seen from nodes[0] + # and return the block height which listsinceblock now exposes since a5e7795. + transactions = self.nodes[0].listsinceblock(nodes1_last_blockhash)['transactions'] + found = next(tx for tx in transactions if tx['txid'] == senttx) + assert_equal(found['blockheight'], self.nodes[0].getblockheader(nodes2_first_blockhash)['height']) def test_double_spend(self): ''' diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index b9c5c038d0..70eea34363 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -7,14 +7,6 @@ deadlock:WalletBatch # Intentional deadlock in tests deadlock:TestPotentialDeadLockDetected -# Race due to unprotected calls to thread-unsafe BOOST_TEST_MESSAGE from different threads: -# * G_TEST_LOG_FUN in the index thread -# * boost test case invoker (entering a test case) in the main thread -# TODO: get rid of BOOST_ macros, see also https://github.com/bitcoin/bitcoin/issues/8670 -race:blockfilter_index_initial_sync_invoker -race:txindex_initial_sync_invoker -race:validation_block_tests::TestSubscriber - # Wildcard for all gui tests, should be replaced with non-wildcard suppressions race:src/qt/test/* deadlock:src/qt/test/* |