test: Make torcontrol max line length test stricter and test boundaries.

Adds a check that at the boundary of MAX_LINE_LENGTH, no disconnect
occurs.

Also makes the overlength test message exactly MAX_LINE_LENGTH + 1 to
test the boundary.

Drops the redundant node liveness check, which is covered by the later
check that the node reconnects.
This commit is contained in:
David Gumberg
2026-04-15 10:54:34 -07:00
parent ab5889796f
commit 8b68287bf9

View File

@@ -3,6 +3,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test torcontrol functionality with a mock Tor control server."""
from contextlib import contextmanager
import socket
import threading
from test_framework.test_framework import BitcoinTestFramework
@@ -124,6 +125,20 @@ class TorControlTest(BitcoinTestFramework):
self.wait_until(lambda: len(mock_tor.received_commands) >= 1, timeout=10)
assert_equal(mock_tor.received_commands[0], "PROTOCOLINFO 1")
@contextmanager
def expect_disconnect(self, expect, mock_tor):
initial_len = len(mock_tor.received_commands)
yield
if expect:
# Expect to receive a PROTOCOLINFO 1 on reconnect, bumping the received
# commands length.
self.wait_until(lambda: len(mock_tor.received_commands) == initial_len + 1)
assert_equal(mock_tor.received_commands[initial_len], "PROTOCOLINFO 1")
else:
# No disconnect, so no reconnect message
ensure_for(duration=2, f=lambda: len(mock_tor.received_commands) == initial_len)
def test_basic(self):
self.log.info("Test Tor control basic functionality")
@@ -202,19 +217,23 @@ class TorControlTest(BitcoinTestFramework):
mock_tor.stop()
def test_oversized_line(self):
self.log.info("Test that Tor control disconnects on oversized response lines")
mock_tor = MockTorControlServer(self.next_port(), manual_mode=True)
self.restart_with_mock(mock_tor)
# Send a single line longer than MAX_LINE_LENGTH. The node should disconnect.
MAX_LINE_LENGTH = 100000
mock_tor.send_raw("250-" + ("A" * (MAX_LINE_LENGTH + 1)) + "\r\n")
ensure_for(duration=2, f=lambda: self.nodes[0].process.poll() is None)
# Connection should be dropped and retried, causing another PROTOCOLINFO.
self.wait_until(lambda: len(mock_tor.received_commands) >= 2, timeout=10)
assert_equal(mock_tor.received_commands[1], "PROTOCOLINFO 1")
self.log.info("Test that Tor control does not disconnect with a MAX_LINE_LENGTH line.")
with self.expect_disconnect(False, mock_tor):
msg = "250-" + ("A" * (MAX_LINE_LENGTH - 5)) + "\r"
assert_equal(len(msg), MAX_LINE_LENGTH)
# The \n is not counted in line length.
mock_tor.send_raw(msg + "\n")
self.log.info("Test that Tor control disconnects with a MAX_LINE_LENGTH + 1 line")
with self.expect_disconnect(True, mock_tor):
msg = "250-" + ("A" * (MAX_LINE_LENGTH - 4)) + "\r"
assert_equal(len(msg), MAX_LINE_LENGTH + 1)
mock_tor.send_raw(msg + "\n")
mock_tor.stop()