Test Details Overview

Rework the network tests (#5226)

* Move the endpoint and address tests to the network functions suite

`parse_endpoint.*` and `network.ipv6` exercise `nano::parse_endpoint` and
the byte layout of a v4-mapped address, nothing of `nano::network`. They
join the other address helpers in network_functions.cpp, the latter under
that suite's name.

* Move the vote quorum tests to the election suite

`receivable_processor.confirm_insufficient_pos` and `confirm_sufficient_pos`
feed one vote to an election through `node.inbound` and check whether its
weight reaches quorum. That is election behaviour, so they move to
election.cpp under the `election` suite.

* Move the auto-receive tests to the wallet suite

`receivable_processor.send_with_receive` and `network.receive_weight_change`
check that inserting a key into a wallet receives the pending send and that
the receiving account's representative gains the weight. Both are wallet
behaviour, so they move to wallet.cpp under the `wallet` suite.

`send_with_receive` handed the same block object to both nodes' block
processors, which TSan reports as a race; the second node now gets its own
copy.

* Rename peer_container.cpp to tcp_channels.cpp

There is no peer_container class. The file tests the channel container
behind `nano::network`, so it takes the container's name, and its
`peer_container` and `channels` suites become `tcp_channels`.

* Move the handshake and message rejection tests to the TCP server suite

`network.send_node_id_handshake_tcp`, `send_insufficient_work`,
`filter_invalid_network_bytes`, `filter_invalid_version_using` and
`tcp_channels.depeer_on_outdated_version` assert handshake stats or
`tcp_server_message_error` counts: what the TCP server does with a
connection or a message. They join `handshake_outdated_protocol_version`
and `handshake_wrong_network_id` in tcp_server.cpp, with that file's block
descriptions.

* Give the peer exclusion test a file of its own

`peer_exclusion.validate` tests `nano::peer_exclusion` on its own, with no
node or network around it. It moves to peer_exclusion.cpp without the
`namespace nano` wrapper, since `score` and `until` are public.

* Move the loopback channel test to the inproc suite

`network.loopback_channel` checks what an inproc channel reports about its
node. It joins the other inproc channel tests under the `inproc` suite.

* Give the bandwidth limiter test a file of its own

`network.bandwidth_limiter_with_burst` sends over inproc channels and counts
drops by the node's outbound limiter. rate_limiting.cpp covers only the
token bucket, so the node-level limiter gets bandwidth_limiter.cpp.

* Drop the network tests that prove nothing about the network

`network.tcp_connection` accepts and connects raw boost sockets with no nano
code in between. `ipv6_from_ipv4` asserts boost's own address mapping.
`endpoint_bad_fd` waits ten seconds for a port that `network::stop` zeroes
synchronously. `send_valid_confirm_ack` sends no confirm_ack and is
`send_valid_publish` minus one assertion. `multi_keepalive` is peer discovery
through a third node, which `peer_discovery_via_peering_only_node` proves.
`tcp_channels.empty_peers` is the first three lines of `cleanup_purge`.

The three DISABLED tests have been off since 2024-11: the two bandwidth
limiter tests send the same droppable publish as both the droppable and
the "non-droppable" message, and `tcp_channel_cleanup_works` is a retry
loop around a race it documents itself.

* Rewrite the network tests that wait for nothing or test the old API

`list_fanout` expected a fanout of one with no peers, from before the
configured minimum, and compared floats with `ASSERT_EQ`; it is now `fanout`,
on a minimum of one so that both arms of the formula show with three peers.
`reachout` built a config disabling reachout and then passed flags instead,
so reachout ran; it uses the flag now and also checks that a pending attempt
blocks a second. `tcp_no_accept_excluded_peers` spun on `add` until `check`
turned true and then cleaned up attempts and cookies by hand; two strikes
reach the limit, and the reconnect comes from the side that never recorded
an attempt.

`duplicate_revert_vote` and `no_self_incoming` replace their timed waits
with the drop stat and the handshake stat that mark the event.

`send_discarded_publish` and `send_invalid_publish` fold into `flood_block`,
which checks the fanout cut; their ledger assertions were the block
processor's. `duplicate_revert_publish` loses the node and channel it never
used. The two `purge_dead_channel` tests drop the six bootstrap flags
nothing under nano/node reads, the debug observer and the unused node
binding.

network.cpp settles on block descriptions above each described test and
one-line step comments inside; tcp_channels.cpp stays on line comments.
The includes only the moved and dropped tests used go with them.

* Test the network's listing, flooding, capacity and handshake API

`list` checks the connection order, the cut, the filter and the version
form. `send_to_buffer` sends one serialized buffer to a range and an empty
range. `flood_block_initial` reaches the representative and a fanout of the
others with the counts adding up. `flood_message_all` stalls one channel by
starving the outbound limiter and shows the flood, `flood_block_all` and
the capacity check skipping it for that traffic type only.
`flood_block_many` checks the delay and the callback, `check_capacity` the
half-of-target rule in its three forms, `flood_keepalive` the scaled
fanouts, and `fill_keepalive_self` now asserts the first two slots, with
`fill_keepalive_self_external` for a configured external address.

`syn_cookies` covers one cookie per endpoint, the cap per IP, the single
hand-back and the purge. `verify_handshake_response` walks every rejection
in order and shows which ones consume the cookie,
and `prepare_handshake_response` what each handshake version carries.

`tcp_channels.keepalive_idle` in tcp_channels.cpp shows the keepalive sweep
waking only the channels that have sent nothing since its cutoff. The sweep
now takes that cutoff from its caller, as `purge` does, so the test moves
the cutoff instead of backdating a channel the rest of the node keeps
sending on. Each declaration in tcp_channels.hpp gets a comment on the way.

* Test the node's bandwidth limiter instead of an inproc send that never meets it

`bandwidth_limiter.with_burst` sent four publishes over inproc channels and
checked that none was dropped. An inproc channel hands the message straight
to the destination and never asks the limiter, so the test could not fail
and has not since the channel traffic rework.

The two tests in its place cover what the node's limiter adds to the token
bucket: one bucket for bootstrap server traffic and one for every other
traffic type, each from its own limit and burst ratio, the retry hint on a
refused request, and the super rebroadcaster flag lifting the generic limit
while the bootstrap limit stays.

* Describe and comment the tests moved out of the network suite

The relocations moved these tests as they were, so they sat next to tests of
the newer style with no description, no step comments and the old
initialization syntax. Each now has a block description saying what it
proves, step comments inside, and modern declarations; what they assert is
unchanged except where noted.

`tcp_server.send_node_id_handshake_tcp` counted handshake messages with the
node that connects expecting two, which only a second connection in the
other direction can give it; it now expects the two on the accepting side
and one on the connecting side, as the two-step handshake sends them, and
one keepalive on each side rather than two. `peer_exclusion.validate` also
checks that the second strike excludes the peer. `inproc.loopback_channel`
no longer starts a second node it never used.

* Describe and comment the network tests kept as they were

The rewrite pass left the tests whose behaviour was sound untouched, which
left them in the old style next to the rewritten ones. Each now has a
description, step comments and modern declarations, and `has_channel`
replaces the lambda three of them defined to look a channel up in the list.
The channel container tests carried their descriptions as line comments
while every other network suite uses blocks; every description above a test
in tcp_channels.cpp is now a block like the rest.

`send_valid_publish` no longer loads wallets it did not use and checks that
the node's latest block becomes the one published rather than merely
changing. `cleanup_purge` checks that the purged channel is closed, not
only counted, and purges it with a cutoff past any send the node can
make in the meantime. `reserved_ip_is_not_a_peer` loops over its
addresses with a line naming the ranges they come from.

* Keep the inproc send callback's state alive past an early return

`inproc.send_callback` captured its locals by reference in a callback
that runs on an io thread, so after a timed out wait returned from the
test a late callback would write to freed stack. It now records into a
`nano::test::shared_result`, a new helper next to `shared_flag` whose
copies share the values a callback reports, so the callback holds it by
value. `wallet.send_async` records the block it gets back the same way,
which also moves its check from the wallet's thread to the test's.

__________

Type: commit

Hash: 39b3d4fc7a103a90f82fed8e735bb52094f88ff7

Created: 2 day(s) ago

__________

gr0v1ty/nano-node:39b3d4fc7a103a90f82fed8e735bb52094f88ff7

Test Results

Test Case Status Duration Median Deviation Log Graph
5n4pr_conf_10k_bintree FAIL N/A N/A GitHub job logs -
5n4pr_conf_10k_change FAIL N/A N/A GitHub job logs -
5n4pr_conf_change_dependant FAIL N/A N/A GitHub job logs -
5n4pr_conf_change_independant FAIL N/A N/A GitHub job logs -
5n4pr_conf_send_dependant FAIL N/A N/A GitHub job logs -
5n4pr_conf_send_independant FAIL N/A N/A GitHub job logs -
5n4pr_rocks_10k_bintree FAIL N/A N/A GitHub job logs -
5n4pr_rocks_10k_change FAIL N/A N/A GitHub job logs -