-
Notifications
You must be signed in to change notification settings - Fork 37.7k
net: Use mockable time for ping/pong, add tests #18638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
fa3076a
to
5555f1c
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. Coverage
Updated at: 2020-04-15T00:09:25.322904. |
5555f1c
to
fa7bbfb
Compare
fafdfe8
to
fa2edad
Compare
fa2edad
to
fa21481
Compare
fa21481
to
fa3fcb4
Compare
Concept ACK. Won't this potentially cause issues (e.g. ping timeouts) in P2P tests that already use mockable time for other things, but are not expecting it to have an effect on pings? (seems not, given that all the tests still pass) |
The Other tests should not be affected. If they are, it should be trivial to fix them up. |
Concept ACK: mockable is better than non-mockable :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK fa94d6f changes per git range-diff b3ec1fe fabb382 fa94d6f
are updates for a recent merge converting pointers to references in net processing code. Re-did clang and fuzz debug builds, re-ran the new test p2p_ping
and the process_message
and p2p_transport_deserializer
fuzz tests locally.
from test_framework.test_framework import BitcoinTestFramework | ||
from test_framework.util import assert_equal | ||
|
||
PING_INTERVAL = 2 * 60 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if you retouch, could add a comment expressing the time units or along the lines of:
PING_INTERVAL = 2 * 60 # 2 minutes (corresponds to net_processing::PING_INTERVAL)
fa94d6f
to
fa33654
Compare
Rebased. Should be easy to re-ACK with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review re-ACK fa33654 re-read code, verified rebase per git range-diff 4b5c919 fa94d6f fa33654
, previous tested ACKs still valid
|
||
self.log.info('Check that ping is sent after connection is established') | ||
no_pong_node = self.nodes[0].add_p2p_connection(NodeNoPong()) | ||
self.mock_forward(3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is peertimeout
right? If yes, we use peertimeout
at 3 places any maybe it's more clear to define it at the outermost scope as well like PING_INTERVAL
? Or maybe there's no need :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
peertimeout
is wall clock time, not mock time, I think. So this can be any value, as long as it matches pingwait=3 below, I'd say
ACK faab4aa, ran functional tests and read the python scripts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fa33654
Reviewed, verified everything runs.
I enjoyed how each sub-test flows into the next one. Hard to see at first but they really work together.
A few questions.
self.log.info('Check that ping is sent after connection is established') | ||
no_pong_node = self.nodes[0].add_p2p_connection(NodeNoPong()) | ||
self.mock_forward(3) | ||
assert no_pong_node.last_message.pop('ping').nonce != 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why pop here, as opposed to just accessing the value? Seems like having (message_count['ping'] == 1 and 'ping' not in last_message) == True
could be confusing.
Maybe decrementing message_count['ping']
every pop is an easier solution, being that this idea is used throughout the test.
assert no_pong_node.last_message.pop('ping').nonce != 0 | |
assert no_pong_node.last_message['ping'].nonce != 0 |
Or maybe
assert no_pong_node.last_message.pop('ping').nonce != 0 | |
assert no_pong_node.last_message.get('ping').nonce != 0 |
or
assert no_pong_node.last_message.pop('ping').nonce != 0 | |
assert no_pong_node.last_message.pop('ping').nonce != 0 | |
no_pong_node.message_count['ping'] -= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't aware that message_count
exists, nor am I using it in this test. Given that it is almost unused right now and causes (potential) confusion, I'd say to remove it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reason I use pop is to ensure the value is discarded after a read and has no way to poison follow-up test cases
with self.nodes[0].assert_debug_log([ | ||
'pong peer=0: Unsolicited pong without ping, 0 expected, 0 received, 8 bytes', | ||
]): | ||
no_pong_node.send_and_ping(msg_pong()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why send_and_ping
and not send_message
, here and throughout? Doesn't seem like it would make a difference, and maybe it's best that we don't have extraneous pings and pongs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like to use assert_debug_log
as a way to synchronize/poll for a change
send_and_ping
is a way to flush all messages in the buffer (on both sides, send and receive) and ensure they are processed (and any errors have been logged).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, sending a ping and receiving a ping should never interfere, unless I am missing something obvious
from test_framework.messages import ( | ||
msg_pong, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: single line for a single import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Can be fixed in a follow-up
Thanks for the review everyone. If there are ways to improve the test, I am happy to review them in a follow-up |
fa33654 net: Use mockable time for ping/pong, add tests (MarcoFalke) faab4aa util: Add count_microseconds helper (MarcoFalke) Pull request description: Switch `CNode::m_ping_start` and `CNetMessage::m_time` to mockable time, so that tests can be added. Mockable time is also type-safe, since it uses `std::chrono` ACKs for top commit: jonatack: Code review re-ACK fa33654 re-read code, verified rebase per `git range-diff 4b5c919 fa94d6f fa33654`, previous tested ACKs still valid troygiorshev: ACK fa33654 Tree-SHA512: 7d632bd6019ce7c882029e71b667a61517e783af82755a85dd979ef09380934e172dec8b8f91d57b200a30a6e096aeaf01f19fee7f3aed0e0e871c72eb44d70e
Summary: ``` Switch CNode::m_ping_start and CNetMessage::m_time to mockable time, so that tests can be added. Mockable time is also type-safe, since it uses std::chrono ``` Backport of core [[bitcoin/bitcoin#18638 | PR18638]]. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, majcosta Reviewed By: #bitcoin_abc, majcosta Differential Revision: https://reviews.bitcoinabc.org/D9129
Switch
CNode::m_ping_start
andCNetMessage::m_time
to mockable time, so that tests can be added.Mockable time is also type-safe, since it uses
std::chrono