Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_ping.py
Show All 33 Lines | |||||
class PingPongTest(BitcoinTestFramework): | class PingPongTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
# Set the peer connection timeout low. It does not matter for this | # Set the peer connection timeout low. It does not matter for this | ||||
# test, as long as it is less than TIMEOUT_INTERVAL. | # test, as long as it is less than TIMEOUT_INTERVAL. | ||||
self.extra_args = [['-peertimeout=1']] | self.extra_args = [["-peertimeout=1"]] | ||||
def check_peer_info(self, *, pingtime, minping, pingwait): | def check_peer_info(self, *, pingtime, minping, pingwait): | ||||
stats = self.nodes[0].getpeerinfo()[0] | stats = self.nodes[0].getpeerinfo()[0] | ||||
assert_equal(stats.pop('pingtime', None), pingtime) | assert_equal(stats.pop("pingtime", None), pingtime) | ||||
assert_equal(stats.pop('minping', None), minping) | assert_equal(stats.pop("minping", None), minping) | ||||
assert_equal(stats.pop('pingwait', None), pingwait) | assert_equal(stats.pop("pingwait", None), pingwait) | ||||
def mock_forward(self, delta): | def mock_forward(self, delta): | ||||
self.mock_time += delta | self.mock_time += delta | ||||
self.nodes[0].setmocktime(self.mock_time) | self.nodes[0].setmocktime(self.mock_time) | ||||
def run_test(self): | def run_test(self): | ||||
self.mock_time = int(time.time()) | self.mock_time = int(time.time()) | ||||
self.mock_forward(0) | self.mock_forward(0) | ||||
self.log.info( | self.log.info("Check that ping is sent after connection is established") | ||||
'Check that ping is sent after connection is established') | |||||
no_pong_node = self.nodes[0].add_p2p_connection(NodeNoPong()) | no_pong_node = self.nodes[0].add_p2p_connection(NodeNoPong()) | ||||
self.mock_forward(3) | self.mock_forward(3) | ||||
assert no_pong_node.last_message.pop('ping').nonce != 0 | assert no_pong_node.last_message.pop("ping").nonce != 0 | ||||
self.check_peer_info(pingtime=None, minping=None, pingwait=3) | self.check_peer_info(pingtime=None, minping=None, pingwait=3) | ||||
self.log.info('Reply without nonce cancels ping') | self.log.info("Reply without nonce cancels ping") | ||||
with self.nodes[0].assert_debug_log(['pong peer=0: Short payload']): | with self.nodes[0].assert_debug_log(["pong peer=0: Short payload"]): | ||||
no_pong_node.send_and_ping(msg_pong_corrupt()) | no_pong_node.send_and_ping(msg_pong_corrupt()) | ||||
self.check_peer_info(pingtime=None, minping=None, pingwait=None) | self.check_peer_info(pingtime=None, minping=None, pingwait=None) | ||||
self.log.info('Reply without ping') | self.log.info("Reply without ping") | ||||
with self.nodes[0].assert_debug_log([ | with self.nodes[0].assert_debug_log( | ||||
'pong peer=0: Unsolicited pong without ping, 0 expected, 0 received, 8 bytes', | [ | ||||
]): | ( | ||||
"pong peer=0: Unsolicited pong without ping, 0 expected, 0" | |||||
" received, 8 bytes" | |||||
), | |||||
] | |||||
): | |||||
no_pong_node.send_and_ping(msg_pong()) | no_pong_node.send_and_ping(msg_pong()) | ||||
self.check_peer_info(pingtime=None, minping=None, pingwait=None) | self.check_peer_info(pingtime=None, minping=None, pingwait=None) | ||||
self.log.info('Reply with wrong nonce does not cancel ping') | self.log.info("Reply with wrong nonce does not cancel ping") | ||||
assert 'ping' not in no_pong_node.last_message | assert "ping" not in no_pong_node.last_message | ||||
with self.nodes[0].assert_debug_log(['pong peer=0: Nonce mismatch']): | with self.nodes[0].assert_debug_log(["pong peer=0: Nonce mismatch"]): | ||||
# mock time PING_INTERVAL ahead to trigger node into sending a ping | # mock time PING_INTERVAL ahead to trigger node into sending a ping | ||||
self.mock_forward(PING_INTERVAL + 1) | self.mock_forward(PING_INTERVAL + 1) | ||||
no_pong_node.wait_until( | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
lambda: 'ping' in no_pong_node.last_message) | |||||
self.mock_forward(9) | self.mock_forward(9) | ||||
# Send the wrong pong | # Send the wrong pong | ||||
no_pong_node.send_and_ping( | no_pong_node.send_and_ping( | ||||
msg_pong(no_pong_node.last_message.pop('ping').nonce - 1)) | msg_pong(no_pong_node.last_message.pop("ping").nonce - 1) | ||||
) | |||||
self.check_peer_info(pingtime=None, minping=None, pingwait=9) | self.check_peer_info(pingtime=None, minping=None, pingwait=9) | ||||
self.log.info('Reply with zero nonce does cancel ping') | self.log.info("Reply with zero nonce does cancel ping") | ||||
with self.nodes[0].assert_debug_log(['pong peer=0: Nonce zero']): | with self.nodes[0].assert_debug_log(["pong peer=0: Nonce zero"]): | ||||
no_pong_node.send_and_ping(msg_pong(0)) | no_pong_node.send_and_ping(msg_pong(0)) | ||||
self.check_peer_info(pingtime=None, minping=None, pingwait=None) | self.check_peer_info(pingtime=None, minping=None, pingwait=None) | ||||
self.log.info('Check that ping is properly reported on RPC') | self.log.info("Check that ping is properly reported on RPC") | ||||
assert 'ping' not in no_pong_node.last_message | assert "ping" not in no_pong_node.last_message | ||||
# mock time PING_INTERVAL ahead to trigger node into sending a ping | # mock time PING_INTERVAL ahead to trigger node into sending a ping | ||||
self.mock_forward(PING_INTERVAL + 1) | self.mock_forward(PING_INTERVAL + 1) | ||||
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message) | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
ping_delay = 29 | ping_delay = 29 | ||||
self.mock_forward(ping_delay) | self.mock_forward(ping_delay) | ||||
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message) | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
no_pong_node.send_and_ping( | no_pong_node.send_and_ping( | ||||
msg_pong(no_pong_node.last_message.pop('ping').nonce)) | msg_pong(no_pong_node.last_message.pop("ping").nonce) | ||||
self.check_peer_info( | ) | ||||
pingtime=ping_delay, | self.check_peer_info(pingtime=ping_delay, minping=ping_delay, pingwait=None) | ||||
minping=ping_delay, | |||||
pingwait=None) | |||||
self.log.info('Check that minping is decreased after a fast roundtrip') | self.log.info("Check that minping is decreased after a fast roundtrip") | ||||
# mock time PING_INTERVAL ahead to trigger node into sending a ping | # mock time PING_INTERVAL ahead to trigger node into sending a ping | ||||
self.mock_forward(PING_INTERVAL + 1) | self.mock_forward(PING_INTERVAL + 1) | ||||
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message) | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
ping_delay = 9 | ping_delay = 9 | ||||
self.mock_forward(ping_delay) | self.mock_forward(ping_delay) | ||||
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message) | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
no_pong_node.send_and_ping( | no_pong_node.send_and_ping( | ||||
msg_pong(no_pong_node.last_message.pop('ping').nonce)) | msg_pong(no_pong_node.last_message.pop("ping").nonce) | ||||
self.check_peer_info( | ) | ||||
pingtime=ping_delay, | self.check_peer_info(pingtime=ping_delay, minping=ping_delay, pingwait=None) | ||||
minping=ping_delay, | |||||
pingwait=None) | |||||
self.log.info('Check that peer is disconnected after ping timeout') | self.log.info("Check that peer is disconnected after ping timeout") | ||||
assert 'ping' not in no_pong_node.last_message | assert "ping" not in no_pong_node.last_message | ||||
self.nodes[0].ping() | self.nodes[0].ping() | ||||
no_pong_node.wait_until(lambda: 'ping' in no_pong_node.last_message) | no_pong_node.wait_until(lambda: "ping" in no_pong_node.last_message) | ||||
with self.nodes[0].assert_debug_log(['ping timeout: 1201.000000s']): | with self.nodes[0].assert_debug_log(["ping timeout: 1201.000000s"]): | ||||
self.mock_forward(TIMEOUT_INTERVAL // 2) | self.mock_forward(TIMEOUT_INTERVAL // 2) | ||||
# Check that sending a ping does not prevent the disconnect | # Check that sending a ping does not prevent the disconnect | ||||
no_pong_node.sync_with_ping() | no_pong_node.sync_with_ping() | ||||
self.mock_forward(TIMEOUT_INTERVAL // 2 + 1) | self.mock_forward(TIMEOUT_INTERVAL // 2 + 1) | ||||
no_pong_node.wait_for_disconnect() | no_pong_node.wait_for_disconnect() | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
PingPongTest().main() | PingPongTest().main() |