Skip to content

Conversation

maflcko
Copy link
Member

@maflcko maflcko commented Apr 14, 2020

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

@maflcko maflcko changed the title net: Make ping mockable, add tests net: Use mocktime for ping/pong, add tests Apr 14, 2020
@maflcko maflcko changed the title net: Use mocktime for ping/pong, add tests net: Use mockable time for ping/pong, add tests Apr 14, 2020
@maflcko maflcko force-pushed the 2004-netMockPing branch 2 times, most recently from fa3076a to 5555f1c Compare April 14, 2020 19:35
@DrahtBot
Copy link
Contributor

DrahtBot commented Apr 14, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, 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

Coverage Change (pull 18638, 0f96c4b) Reference (master, 75fcfda)
Lines +0.0020 % 90.3582 %
Functions +0.1431 % 85.0787 %
Branches +0.0089 % 51.8202 %

Updated at: 2020-04-15T00:09:25.322904.

@laanwj
Copy link
Member

laanwj commented May 4, 2020

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)

@maflcko
Copy link
Member Author

maflcko commented May 4, 2020

The -peertimeout is still measured in wall clock time, and because most of the test run through faster than what the -peertimeout is, this should not lead to issues in general. There are two tests test/functional/feature_maxuploadtarget.py and test/functional/feature_bip68_sequence.py which mine a lot of blocks (more than 100) under mocktime. This can take time when the tests are run under valgrind, so I had to bump the -peertimeout for those tests.

Other tests should not be affected. If they are, it should be trivial to fix them up.

@practicalswift
Copy link
Contributor

Concept ACK: mockable is better than non-mockable :)

Copy link
Member

@jonatack jonatack left a 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
Copy link
Member

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)

@maflcko maflcko force-pushed the 2004-netMockPing branch from fa94d6f to fa33654 Compare June 19, 2020 11:26
@maflcko
Copy link
Member Author

maflcko commented Jun 19, 2020

Rebased. Should be easy to re-ACK with git range-diff bitcoin-core/master A B

Copy link
Member

@jonatack jonatack left a 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)
Copy link
Contributor

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 :)

Copy link
Member Author

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

@fridokus
Copy link
Contributor

ACK faab4aa, ran functional tests and read the python scripts.

Copy link
Contributor

@troygiorshev troygiorshev left a 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
Copy link
Contributor

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.

Suggested change
assert no_pong_node.last_message.pop('ping').nonce != 0
assert no_pong_node.last_message['ping'].nonce != 0

Or maybe

Suggested change
assert no_pong_node.last_message.pop('ping').nonce != 0
assert no_pong_node.last_message.get('ping').nonce != 0

or

Suggested change
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

Copy link
Member Author

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

Copy link
Member Author

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())
Copy link
Contributor

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.

Copy link
Member Author

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).

Copy link
Member Author

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

Comment on lines +10 to +12
from test_framework.messages import (
msg_pong,
)
Copy link
Contributor

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?

Copy link
Member Author

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

@maflcko
Copy link
Member Author

maflcko commented Jul 10, 2020

Thanks for the review everyone. If there are ways to improve the test, I am happy to review them in a follow-up

@maflcko maflcko merged commit 107b855 into bitcoin:master Jul 10, 2020
@maflcko maflcko deleted the 2004-netMockPing branch July 10, 2020 14:40
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jul 10, 2020
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
deadalnix pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Feb 3, 2021
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
kwvg added a commit to kwvg/dash that referenced this pull request Jul 13, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jul 13, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jul 15, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jul 15, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jul 16, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Aug 1, 2021
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants