I agree. I will stick to a meaningful message after a timeout instead of infinite wait (without a message).
I agree with that too. But the parallel with SyncWithValidationInterfaceQueue()
is not very close to the tests in this PR because SyncWithValidationInterfaceQueue()
does not provide fine-grained sync points, see below what I mean.
It is possible to not use the debug log. Here is how it would look like:
0diff --git i/src/net_processing.cpp w/src/net_processing.cpp
1index 1c73ca4eb4..35301a6a2d 100644
2--- i/src/net_processing.cpp
3+++ w/src/net_processing.cpp
4@@ -3529,12 +3529,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
5 // At this point, the outgoing message serialization version can't change.
6 const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
7
8 if (msg_type == NetMsgType::VERACK) {
9 if (pfrom.fSuccessfullyConnected) {
10 LogPrint(BCLog::NET, "ignoring redundant verack message from peer=%d\n", pfrom.GetId());
11+ g_stage_redundant_verack.post();
12 return;
13 }
14
15 if (!pfrom.IsInboundConn()) {
16 const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};
17 LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s%s (%s)\n",
18@@ -3781,12 +3782,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
19 }
20 peer->m_addr_processed += num_proc;
21 peer->m_addr_rate_limited += num_rate_limit;
22 LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
23 vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());
24
25+ g_stage_received_addr.post();
26+
27 m_addrman.Add(vAddrOk, pfrom.addr, 2h);
28 if (vAddr.size() < 1000) peer->m_getaddr_sent = false;
29
30 // AddrFetch: Require multiple addresses to avoid disconnecting on self-announcements
31 if (pfrom.IsAddrFetchConn() && vAddr.size() > 1) {
32 LogPrint(BCLog::NET, "addrfetch connection completed peer=%d; disconnecting\n", pfrom.GetId());
33@@ -3948,12 +3951,15 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
34
35 // Send the rest of the chain
36 if (pindex)
37 pindex = m_chainman.ActiveChain().Next(pindex);
38 int nLimit = 500;
39 LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom.GetId());
40+ if (pindex == nullptr && hashStop.IsNull()) {
41+ g_stage_getblocks_all.post();
42+ }
43 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
44 {
45 if (pindex->GetBlockHash() == hashStop)
46 {
47 LogPrint(BCLog::NET, " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
48 break;
49@@ -4765,26 +4771,31 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
50 } else {
51 // This should never happen
52 sProblem = "Timing mishap";
53 }
54 } else {
55 // Nonce mismatches are normal when pings are overlapping
56- sProblem = "Nonce mismatch";
57 if (nonce == 0) {
58 // This is most likely a bug in another implementation somewhere; cancel this ping
59 bPingFinished = true;
60 sProblem = "Nonce zero";
61+ g_stage_ping_nonce_zero.post();
62+ } else {
63+ sProblem = "Nonce mismatch";
64+ g_stage_ping_nonce_mismatch.post();
65 }
66 }
67 } else {
68 sProblem = "Unsolicited pong without ping";
69+ g_stage_unsolicited_pong_without_ping.post();
70 }
71 } else {
72 // This is most likely a bug in another implementation somewhere; cancel this ping
73 bPingFinished = true;
74 sProblem = "Short payload";
75+ g_stage_ping_short_payload.post();
76 }
77
78 if (!(sProblem.empty())) {
79 LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n",
80 pfrom.GetId(),
81 sProblem,
82@@ -5259,12 +5270,13 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic
83 m_connman.PushMessage(&node_to, msgMaker.Make(NetMsgType::PING, nonce));
84 } else {
85 // Peer is too old to support ping command with nonce, pong will never arrive.
86 peer.m_ping_nonce_sent = 0;
87 m_connman.PushMessage(&node_to, msgMaker.Make(NetMsgType::PING));
88 }
89+ g_stage_sending_ping.post();
90 }
91 }
92
93 void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
94 {
95 // Nothing to do for non-address-relay peers
96@@ -5928,6 +5940,15 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
97 if (!vGetData.empty())
98 m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
99 } // release cs_main
100 MaybeSendFeefilter(*pto, *peer, current_time);
101 return true;
102 }
103+
104+CSemaphore g_stage_received_addr{0};
105+CSemaphore g_stage_getblocks_all{0};
106+CSemaphore g_stage_sending_ping{0};
107+CSemaphore g_stage_ping_short_payload{0};
108+CSemaphore g_stage_unsolicited_pong_without_ping{0};
109+CSemaphore g_stage_ping_nonce_mismatch{0};
110+CSemaphore g_stage_ping_nonce_zero{0};
111+CSemaphore g_stage_redundant_verack{0};
112diff --git i/src/net_processing.h w/src/net_processing.h
113index 1bd2b1e8ca..de4a12705f 100644
114--- i/src/net_processing.h
115+++ w/src/net_processing.h
116@@ -91,7 +91,16 @@ public:
117 const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) = 0;
118
119 /** This function is used for testing the stale tip eviction logic, see denialofservice_tests.cpp */
120 virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) = 0;
121 };
122
123+extern CSemaphore g_stage_received_addr;
124+extern CSemaphore g_stage_getblocks_all;
125+extern CSemaphore g_stage_sending_ping;
126+extern CSemaphore g_stage_ping_short_payload;
127+extern CSemaphore g_stage_unsolicited_pong_without_ping;
128+extern CSemaphore g_stage_ping_nonce_mismatch;
129+extern CSemaphore g_stage_ping_nonce_zero;
130+extern CSemaphore g_stage_redundant_verack;
131+
132 #endif // BITCOIN_NET_PROCESSING_H
133diff --git i/src/test/net_msg_tests.cpp w/src/test/net_msg_tests.cpp
134index 49c97c1440..17bd74cb3a 100644
135--- i/src/test/net_msg_tests.cpp
136+++ w/src/test/net_msg_tests.cpp
137@@ -63,25 +63,27 @@ BOOST_AUTO_TEST_CASE(initial_messages_exchange)
138
139 BOOST_AUTO_TEST_CASE(addr)
140 {
141 const auto pipes{m_sockets_pipes.PopFront()};
142 std::vector<CAddress> addresses{5};
143
144- ASSERT_DEBUG_LOG_WAIT(strprintf("Received addr: %u addresses", addresses.size()), 30s);
145+ BOOST_REQUIRE(!g_stage_received_addr.try_wait());
146 pipes->recv.PushNetMsg(NetMsgType::ADDRV2, addresses);
147+ g_stage_received_addr.wait();
148 }
149
150 BOOST_AUTO_TEST_CASE(getblocks)
151 {
152 const auto pipes{m_sockets_pipes.PopFront()};
153 std::vector<uint256> hashes{5};
154 CBlockLocator block_locator{std::move(hashes)};
155 uint256 hash_stop;
156
157- ASSERT_DEBUG_LOG_WAIT("getblocks -1 to end", 30s);
158+ BOOST_REQUIRE(!g_stage_getblocks_all.try_wait());
159 pipes->recv.PushNetMsg(NetMsgType::GETBLOCKS, block_locator, hash_stop);
160+ g_stage_getblocks_all.wait();
161 }
162
163 BOOST_AUTO_TEST_CASE(ping)
164 {
165 const auto pipes{m_sockets_pipes.PopFront()};
166
167@@ -132,14 +134,16 @@ BOOST_AUTO_TEST_CASE(ping)
168 }
169 }
170 };
171
172 auto SendPing = [&]() {
173 {
174- ASSERT_DEBUG_LOG_WAIT("sending ping", 30s);
175+ while (g_stage_sending_ping.try_wait())
176+ ;
177 SetMockTime(GetMockTime() + PING_INTERVAL + 1s);
178+ g_stage_sending_ping.wait();
179 }
180 return GetPingNonceSent();
181 };
182
183 BOOST_TEST_MESSAGE("Ensure initial messages exchange has completed with the sending of a ping "
184 "with nonce != 0 and the ping stats indicate a pending ping.");
185@@ -147,37 +151,41 @@ BOOST_AUTO_TEST_CASE(ping)
186 auto time_elapsed = 1s;
187 SetMockTime(GetMockTime() + time_elapsed);
188 WaitForPingStats(/*min=*/std::chrono::microseconds::max(), /*last=*/0us, /*wait=*/time_elapsed);
189
190 BOOST_TEST_MESSAGE("Check that receiving a PONG without nonce cancels our PING");
191 {
192- ASSERT_DEBUG_LOG_WAIT("Short payload", 30s);
193+ BOOST_REQUIRE(!g_stage_ping_short_payload.try_wait());
194 pipes->recv.PushNetMsg(NetMsgType::PONG);
195+ g_stage_ping_short_payload.wait();
196 }
197 WaitForPingStats(/*min=*/std::chrono::microseconds::max(), /*last=*/0us, /*wait=*/0us);
198
199 BOOST_TEST_MESSAGE("Check that receiving an unrequested PONG is logged and ignored");
200 {
201- ASSERT_DEBUG_LOG_WAIT("Unsolicited pong without ping", 30s);
202+ BOOST_REQUIRE(!g_stage_unsolicited_pong_without_ping.try_wait());
203 pipes->recv.PushNetMsg(NetMsgType::PONG, /*nonce=*/uint64_t{0});
204+ g_stage_unsolicited_pong_without_ping.wait();
205 }
206
207 BOOST_TEST_MESSAGE("Check that receiving a PONG with the wrong nonce does not cancel our PING");
208 uint64_t nonce{SendPing()};
209 {
210- ASSERT_DEBUG_LOG_WAIT("Nonce mismatch", 30s);
211+ BOOST_REQUIRE(!g_stage_ping_nonce_mismatch.try_wait());
212 pipes->recv.PushNetMsg(NetMsgType::PONG, nonce + 1);
213+ g_stage_ping_nonce_mismatch.wait();
214 }
215 time_elapsed = 5s;
216 SetMockTime(GetMockTime() + time_elapsed);
217 WaitForPingStats(/*min=*/std::chrono::microseconds::max(), /*last=*/0us, /*wait=*/time_elapsed);
218
219 BOOST_TEST_MESSAGE("Check that receiving a PONG with nonce=0 cancels our PING");
220 {
221- ASSERT_DEBUG_LOG_WAIT("Nonce zero", 30s);
222+ BOOST_REQUIRE(!g_stage_ping_nonce_zero.try_wait());
223 pipes->recv.PushNetMsg(NetMsgType::PONG, /*nonce=*/uint64_t{0});
224+ g_stage_ping_nonce_zero.wait();
225 }
226 WaitForPingStats(/*min=*/std::chrono::microseconds::max(), /*last=*/0us, /*wait=*/0us);
227
228 BOOST_TEST_MESSAGE("Check that receiving a PONG with the correct nonce cancels our PING");
229 nonce = SendPing();
230 time_elapsed = 5s;
231@@ -187,11 +195,12 @@ BOOST_AUTO_TEST_CASE(ping)
232 }
233
234 BOOST_AUTO_TEST_CASE(redundant_verack)
235 {
236 const auto pipes{m_sockets_pipes.PopFront()};
237
238- ASSERT_DEBUG_LOG_WAIT("ignoring redundant verack message", 30s);
239+ BOOST_REQUIRE(!g_stage_redundant_verack.try_wait());
240 pipes->recv.PushNetMsg(NetMsgType::VERACK);
241+ g_stage_redundant_verack.wait();
242 }
243
244 BOOST_AUTO_TEST_SUITE_END()
I could be missing some easier alternative. Let me know if you have something better in mind.