mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-12 02:07:39 +01:00
test: add functional tests for the new getnetmsgstats RPC
Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
This commit is contained in:
parent
0978d7d050
commit
db442f3d6e
1 changed files with 173 additions and 0 deletions
|
@ -10,6 +10,7 @@ Tests correspond to code in rpc/net.cpp.
|
|||
from decimal import Decimal
|
||||
from itertools import product
|
||||
import platform
|
||||
import random
|
||||
import time
|
||||
|
||||
import test_framework.messages
|
||||
|
@ -90,6 +91,7 @@ class NetTest(BitcoinTestFramework):
|
|||
self.test_sendmsgtopeer()
|
||||
self.test_getaddrmaninfo()
|
||||
self.test_getrawaddrman()
|
||||
self.test_getnetmsgstats()
|
||||
|
||||
def test_connection_count(self):
|
||||
self.log.info("Test getconnectioncount")
|
||||
|
@ -202,6 +204,177 @@ class NetTest(BitcoinTestFramework):
|
|||
self.wait_until(lambda: peer_after()['bytesrecv_per_msg'].get('pong', 0) >= peer_before['bytesrecv_per_msg'].get('pong', 0) + ping_size, timeout=1)
|
||||
self.wait_until(lambda: peer_after()['bytessent_per_msg'].get('ping', 0) >= peer_before['bytessent_per_msg'].get('ping', 0) + ping_size, timeout=1)
|
||||
|
||||
def test_getnetmsgstats(self):
|
||||
self.log.info("Test getnetmsgstats")
|
||||
|
||||
self.restart_node(0)
|
||||
node0 = self.nodes[0]
|
||||
self.connect_nodes(0, 1) # Generate some traffic.
|
||||
# Wait for the initial messages to be sent/received (don't disconnect too early). "sendheaders" is the last one.
|
||||
self.wait_until(lambda: "sendheaders" in node0.getnetmsgstats()["recv"]["not_publicly_routable"]["manual"])
|
||||
self.wait_until(lambda: "sendheaders" in node0.getnetmsgstats()["sent"]["not_publicly_routable"]["manual"])
|
||||
self.disconnect_nodes(0, 1) # Avoid random/unpredictable packets (e.g. ping) messing with the tests below.
|
||||
assert_equal(len(node0.getpeerinfo()), 0)
|
||||
|
||||
# In v2 getnettotals counts also bytes that are not accounted at any message (the v2 handshake).
|
||||
# Also the v2 handshake's size could vary.
|
||||
if not self.options.v2transport:
|
||||
self.log.debug("Compare byte count getnetmsgstats vs getnettotals")
|
||||
nettotals = self.nodes[0].getnettotals()
|
||||
stats_net_con_msg = self.nodes[0].getnetmsgstats(aggregate_by=["network", "connection_type", "message_type"])
|
||||
assert_equal(nettotals["totalbytessent"], stats_net_con_msg["sent"]["bytes"])
|
||||
assert_equal(nettotals["totalbytesrecv"], stats_net_con_msg["recv"]["bytes"])
|
||||
|
||||
self.log.debug("Test full (un-aggregated) output is as expected")
|
||||
stats_full = node0.getnetmsgstats()
|
||||
if self.options.v2transport:
|
||||
assert_equal(
|
||||
stats_full,
|
||||
{
|
||||
"recv": {
|
||||
"not_publicly_routable": {
|
||||
"manual": {
|
||||
"addrv2": {"bytes": 63, "count": 1},
|
||||
"feefilter": {"bytes": 29, "count": 1},
|
||||
"getheaders": {"bytes": 666, "count": 1},
|
||||
"headers": {"bytes": 103, "count": 1},
|
||||
"ping": {"bytes": 29, "count": 1},
|
||||
"pong": {"bytes": 29, "count": 1},
|
||||
"sendaddrv2": {"bytes": 33, "count": 1},
|
||||
"sendcmpct": {"bytes": 30, "count": 1},
|
||||
"sendheaders": {"bytes": 33, "count": 1},
|
||||
"verack": {"bytes": 33, "count": 1},
|
||||
"version": {"bytes": 147, "count": 1},
|
||||
"wtxidrelay": {"bytes": 33, "count": 1},
|
||||
}
|
||||
}
|
||||
},
|
||||
"sent": {
|
||||
"not_publicly_routable": {
|
||||
"manual": {
|
||||
"feefilter": {"bytes": 29, "count": 1},
|
||||
"getaddr": {"bytes": 33, "count": 1},
|
||||
"getheaders": {"bytes": 666, "count": 1},
|
||||
"headers": {"bytes": 103, "count": 1},
|
||||
"ping": {"bytes": 29, "count": 1},
|
||||
"pong": {"bytes": 29, "count": 1},
|
||||
"sendaddrv2": {"bytes": 33, "count": 1},
|
||||
"sendcmpct": {"bytes": 30, "count": 1},
|
||||
"sendheaders": {"bytes": 33, "count": 1},
|
||||
"verack": {"bytes": 33, "count": 1},
|
||||
"version": {"bytes": 147, "count": 1},
|
||||
"wtxidrelay": {"bytes": 33, "count": 1},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
else:
|
||||
assert_equal(
|
||||
stats_full,
|
||||
{
|
||||
"recv": {
|
||||
"not_publicly_routable": {
|
||||
"manual": {
|
||||
"addrv2": {"bytes": 66, "count": 1},
|
||||
"feefilter": {"bytes": 32, "count": 1},
|
||||
"getheaders": {"bytes": 669, "count": 1},
|
||||
"headers": {"bytes": 106, "count": 1},
|
||||
"ping": {"bytes": 32, "count": 1},
|
||||
"pong": {"bytes": 32, "count": 1},
|
||||
"sendaddrv2": {"bytes": 24, "count": 1},
|
||||
"sendcmpct": {"bytes": 33, "count": 1},
|
||||
"sendheaders": {"bytes": 24, "count": 1},
|
||||
"verack": {"bytes": 24, "count": 1},
|
||||
"version": {"bytes": 138, "count": 1},
|
||||
"wtxidrelay": {"bytes": 24, "count": 1},
|
||||
}
|
||||
}
|
||||
},
|
||||
"sent": {
|
||||
"not_publicly_routable": {
|
||||
"manual": {
|
||||
"feefilter": {"bytes": 32, "count": 1},
|
||||
"getaddr": {"bytes": 24, "count": 1},
|
||||
"getheaders": {"bytes": 669, "count": 1},
|
||||
"headers": {"bytes": 106, "count": 1},
|
||||
"ping": {"bytes": 32, "count": 1},
|
||||
"pong": {"bytes": 32, "count": 1},
|
||||
"sendaddrv2": {"bytes": 24, "count": 1},
|
||||
"sendcmpct": {"bytes": 33, "count": 1},
|
||||
"sendheaders": {"bytes": 24, "count": 1},
|
||||
"verack": {"bytes": 24, "count": 1},
|
||||
"version": {"bytes": 138, "count": 1},
|
||||
"wtxidrelay": {"bytes": 24, "count": 1},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
self.log.debug("Check that aggregation works correctly")
|
||||
|
||||
def sum_all(json):
|
||||
if "bytes" in json:
|
||||
return dict(bytes=json["bytes"], count=json["count"])
|
||||
|
||||
s = dict(bytes=0, count=0)
|
||||
#print(f'S json={json}')
|
||||
for k, v in json.items():
|
||||
#print(f'S k={k}, v={v}')
|
||||
#print(f'S diving into {v}')
|
||||
sub = sum_all(v)
|
||||
s["bytes"] += sub["bytes"]
|
||||
s["count"] += sub["count"]
|
||||
return s
|
||||
|
||||
stats_aggregated_by_bitcoind = node0.getnetmsgstats(aggregate_by=["direction", "network", "connection_type", "message_type"])
|
||||
stats_aggregated_by_test = sum_all(stats_full)
|
||||
assert_equal(stats_aggregated_by_bitcoind, stats_aggregated_by_test)
|
||||
if not self.options.v2transport:
|
||||
assert_equal(nettotals["totalbytessent"] + nettotals["totalbytesrecv"], stats_aggregated_by_test["bytes"])
|
||||
|
||||
for i in range(1, 16):
|
||||
keywords = []
|
||||
if i & 1:
|
||||
keywords.append("direction")
|
||||
if i & 2:
|
||||
keywords.append("network")
|
||||
if i & 4:
|
||||
keywords.append("connection_type")
|
||||
if i & 8:
|
||||
keywords.append("message_type")
|
||||
random.shuffle(keywords)
|
||||
self.log.debug(f"Test values add up correctly when aggregated by {keywords}")
|
||||
assert_equal(stats_aggregated_by_test, sum_all(node0.getnetmsgstats(aggregate_by=keywords)))
|
||||
|
||||
def get_stats(node):
|
||||
return node.getnetmsgstats(aggregate_by=["network", "connection_type"])
|
||||
|
||||
self.log.debug("Test that message count and total number of bytes increment when a ping message is sent")
|
||||
stats_before_connect = get_stats(node0)
|
||||
node2 = node0.add_p2p_connection(P2PInterface())
|
||||
assert_equal(len(node0.getpeerinfo()), 1)
|
||||
# Wait for the initial PING (that is sent immediately after the connection is estabilshed) to go through.
|
||||
self.wait_until(lambda: get_stats(node0)["sent"]["ping"]["count"] > stats_before_connect["sent"]["ping"]["count"])
|
||||
stats_before_ping = get_stats(node0)
|
||||
node0.ping()
|
||||
self.wait_until(lambda: get_stats(node0)["sent"]["ping"]["count"] > stats_before_ping["sent"]["ping"]["count"])
|
||||
self.wait_until(lambda: get_stats(node0)["sent"]["ping"]["bytes"] > stats_before_ping["sent"]["ping"]["bytes"])
|
||||
|
||||
self.log.debug("Test that when a message is broken in two, the stats only update once the full message has been received")
|
||||
ping_msg = node2.build_message(test_framework.messages.msg_ping(nonce=12345))
|
||||
stats_before_ping = get_stats(node0)
|
||||
# Send the message in two pieces.
|
||||
cut_pos = 7 # Chosen at an arbitrary position within the header.
|
||||
node2.send_raw_message(ping_msg[:cut_pos])
|
||||
assert_equal(get_stats(node0)["recv"]["ping"], stats_before_ping["recv"]["ping"])
|
||||
# Send the rest of the ping.
|
||||
node2.send_raw_message(ping_msg[cut_pos:])
|
||||
self.wait_until(lambda: get_stats(node0)["recv"]["ping"]["count"] == stats_before_ping["recv"]["ping"]["count"] + 1)
|
||||
|
||||
node2.peer_disconnect()
|
||||
|
||||
def test_getnetworkinfo(self):
|
||||
self.log.info("Test getnetworkinfo")
|
||||
info = self.nodes[0].getnetworkinfo()
|
||||
|
|
Loading…
Add table
Reference in a new issue