The unit tests run ShouldDisconnect() but assert nothing about its first two branches. I broke each one and the suite stayed green both times. interface_http.py does reach both, but it blocks on the socket instead of failing. The test below covers both branches, and the new log line with them.
<details>
<summary>test for both branches and the new log line</summary>
@@ -746,6 +746,38 @@ BOOST_AUTO_TEST_CASE(http_request_state_tests)
}
}
+BOOST_AUTO_TEST_CASE(http_should_disconnect_tests)
+{
+ struct Client : HTTPRemoteClient {
+ Client() : HTTPRemoteClient{/*id=*/0, /*addr=*/CService(), /*socket=*/CreateSock(0, 0, 0)} {}
+ using HTTPRemoteClient::MutateRecvBuffer;
+ };
+ constexpr auto timeout{30s};
+ const auto now{Now<SteadySeconds>()};
+
+ // Nothing to disconnect for yet.
+ auto idle{std::make_shared<Client>()};
+ BOOST_CHECK(!idle->ShouldDisconnect(now, timeout, /*disconnect_all=*/false));
+ // A shutdown waits for a connection that is still busy, and it starts busy.
+ BOOST_CHECK(!idle->ShouldDisconnect(now, timeout, /*disconnect_all=*/true));
+ // Past -rpcservertimeout, which a timeout of 0 disables.
+ BOOST_CHECK(idle->ShouldDisconnect(now + timeout + 1s, timeout, /*disconnect_all=*/false));
+ BOOST_CHECK(!idle->ShouldDisconnect(now + timeout + 1s, 0s, /*disconnect_all=*/false));
+
+ // A request handed to a worker holds the idle timeout off until the reply is sent.
+ auto busy{std::make_shared<Client>()};
+ busy->MutateRecvBuffer().append("GET / HTTP/1.0\n\n");
+ auto request{HTTPRemoteClient::TryReadRequest(busy)};
+ BOOST_REQUIRE(request);
+ BOOST_CHECK(!busy->ShouldDisconnect(now + timeout + 1s, timeout, /*disconnect_all=*/false));
+
+ // A malformed request flags the client, and that outranks the rest.
+ auto bad{std::make_shared<Client>()};
+ bad->MutateRecvBuffer().append("GET / HTTP/1.0\nInvalid header with no colon\n\n");
+ BOOST_CHECK(!HTTPRemoteClient::TryReadRequest(bad));
+ BOOST_CHECK(bad->ShouldDisconnect(now, 0s, /*disconnect_all=*/false));
+}
+
BOOST_AUTO_TEST_CASE(http_server_socket_tests)
{
// Hard code the timestamp for the Date header in the HTTP response
@@ -791,6 +823,9 @@ BOOST_AUTO_TEST_CASE(http_server_socket_tests)
// Create a mock client with pre-loaded request data and add it to the local CreateSock queue.
// Keep a handle for the mock client's send and receive pipes so we can examine
// the data it "receives".
+ // No keep-alive, so the server closes once the reply is flushed, and says so.
+ DebugLogHelper find_close{"Done sending to client without keep-alive"};
+
std::shared_ptr<DynSock::Pipes> mock_client_socket_pipes{ConnectClient(std::as_bytes(std::span(full_request)))};
// Wait up to a minute to find and connect the client in the I/O loop
</details>