From 050ef6cca3d19b20f76b7d4bf80b2d82f30f2af6 Mon Sep 17 00:00:00 2001 From: meejah Date: Sat, 29 Jul 2023 04:04:05 -0600 Subject: [PATCH] tor-tests work; refactor ports --- integration/conftest.py | 49 ++++++++++++++++++++++++++++++++++++----- integration/test_i2p.py | 7 +++--- integration/test_tor.py | 15 ++++++------- integration/util.py | 2 +- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/integration/conftest.py b/integration/conftest.py index 837b54aa1..92483da65 100644 --- a/integration/conftest.py +++ b/integration/conftest.py @@ -7,6 +7,7 @@ from __future__ import annotations import os import sys import shutil +from attr import define from time import sleep from os import mkdir, environ from os.path import join, exists @@ -189,7 +190,7 @@ def introducer_furl(introducer, temp_dir): include_args=["temp_dir", "flog_gatherer"], include_result=False, ) -def tor_introducer(reactor, temp_dir, flog_gatherer, request): +def tor_introducer(reactor, temp_dir, flog_gatherer, request, tor_network): intro_dir = join(temp_dir, 'introducer_tor') print("making Tor introducer in {}".format(intro_dir)) print("(this can take tens of seconds to allocate Onion address)") @@ -203,9 +204,7 @@ def tor_introducer(reactor, temp_dir, flog_gatherer, request): request, ( 'create-introducer', - # The control port should agree with the configuration of the - # Tor network we bootstrap with chutney. - '--tor-control-port', 'tcp:localhost:8007', + '--tor-control-port', tor_network.client_control_endpoint, '--hide-ip', '--listen=tor', intro_dir, @@ -306,6 +305,21 @@ def bob(reactor, temp_dir, introducer_furl, flog_gatherer, storage_nodes, reques @pytest.mark.skipif(sys.platform.startswith('win'), 'Tor tests are unstable on Windows') def chutney(reactor, temp_dir: str) -> tuple[str, dict[str, str]]: + """ + Instantiate the "networks/hs-v3" Chutney configuration for a local + Tor network. + + This provides a small, local Tor network that can run v3 Onion + Services. This has 10 tor processes: 3 authorities, 5 + exits+relays, a client (and one service-hosting node we don't use). + + We pin a Chutney revision, so things shouldn't change. Currently, + the ONLY node that exposes a valid SocksPort is "008c" (the + client) on 9008. + + The control ports start at 8000 (so the ControlPort for the one + client node is 8008). + """ # Try to find Chutney already installed in the environment. try: import chutney @@ -363,7 +377,24 @@ def chutney(reactor, temp_dir: str) -> tuple[str, dict[str, str]]: ) pytest_twisted.blockon(proto.done) - return (chutney_dir, {"PYTHONPATH": join(chutney_dir, "lib")}) + return chutney_dir, {"PYTHONPATH": join(chutney_dir, "lib")} + + +@define +class ChutneyTorNetwork: + """ + Represents a running Chutney (tor) network. Returned by the + "tor_network" fixture. + """ + dir: FilePath + environ: dict + client_control_port: int + + @property + def client_control_endpoint(self) -> str: + print("CONTROL", "tcp:localhost:{}".format(self.client_control_port)) + return "tcp:localhost:{}".format(self.client_control_port) + @pytest.fixture(scope='session') @@ -422,3 +453,11 @@ def tor_network(reactor, temp_dir, chutney, request): pytest_twisted.blockon(chutney(("status", basic_network))) except ProcessTerminated: print("Chutney.TorNet status failed (continuing)") + + # the "8008" comes from configuring "networks/basic" in chutney + # and then examining "net/nodes/008c/torrc" for ControlPort value + return ChutneyTorNetwork( + chutney_root, + chutney_env, + 8008, + ) diff --git a/integration/test_i2p.py b/integration/test_i2p.py index 2ee603573..ea3ddb62b 100644 --- a/integration/test_i2p.py +++ b/integration/test_i2p.py @@ -132,8 +132,8 @@ def i2p_introducer_furl(i2p_introducer, temp_dir): @pytest_twisted.inlineCallbacks @pytest.mark.skip("I2P tests are not functioning at all, for unknown reasons") def test_i2p_service_storage(reactor, request, temp_dir, flog_gatherer, i2p_network, i2p_introducer_furl): - yield _create_anonymous_node(reactor, 'carol_i2p', 8008, request, temp_dir, flog_gatherer, i2p_network, i2p_introducer_furl) - yield _create_anonymous_node(reactor, 'dave_i2p', 8009, request, temp_dir, flog_gatherer, i2p_network, i2p_introducer_furl) + yield _create_anonymous_node(reactor, 'carol_i2p', request, temp_dir, flog_gatherer, i2p_network, i2p_introducer_furl) + yield _create_anonymous_node(reactor, 'dave_i2p', request, temp_dir, flog_gatherer, i2p_network, i2p_introducer_furl) # ensure both nodes are connected to "a grid" by uploading # something via carol, and retrieve it using dave. gold_path = join(temp_dir, "gold") @@ -179,9 +179,8 @@ def test_i2p_service_storage(reactor, request, temp_dir, flog_gatherer, i2p_netw @pytest_twisted.inlineCallbacks -def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_gatherer, i2p_network, introducer_furl): +def _create_anonymous_node(reactor, name, request, temp_dir, flog_gatherer, i2p_network, introducer_furl): node_dir = FilePath(temp_dir).child(name) - web_port = "tcp:{}:interface=localhost".format(control_port + 2000) print("creating", node_dir.path) node_dir.makedirs() diff --git a/integration/test_tor.py b/integration/test_tor.py index 4d0ce4f16..d7fed5790 100644 --- a/integration/test_tor.py +++ b/integration/test_tor.py @@ -38,8 +38,8 @@ def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_ne The two nodes can talk to the introducer and each other: we upload to one node, read from the other. """ - carol = yield _create_anonymous_node(reactor, 'carol', 8008, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2) - dave = yield _create_anonymous_node(reactor, 'dave', 8009, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2) + carol = yield _create_anonymous_node(reactor, 'carol', 8100, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2) + dave = yield _create_anonymous_node(reactor, 'dave', 8101, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2) yield util.await_client_ready(carol, minimum_number_of_servers=2, timeout=600) yield util.await_client_ready(dave, minimum_number_of_servers=2, timeout=600) yield upload_to_one_download_from_the_other(reactor, temp_dir, carol, dave) @@ -94,9 +94,8 @@ async def upload_to_one_download_from_the_other(reactor, temp_dir, upload_to: ut @pytest_twisted.inlineCallbacks -def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_gatherer, tor_network, introducer_furl, shares_total: int) -> util.TahoeProcess: +def _create_anonymous_node(reactor, name, web_port, request, temp_dir, flog_gatherer, tor_network, introducer_furl, shares_total: int) -> util.TahoeProcess: node_dir = FilePath(temp_dir).child(name) - web_port = "tcp:{}:interface=localhost".format(control_port + 2000) if node_dir.exists(): raise RuntimeError( "A node already exists in '{}'".format(node_dir) @@ -111,10 +110,10 @@ def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_ sys.executable, '-b', '-m', 'allmydata.scripts.runner', 'create-node', '--nickname', name, - '--webport', web_port, + '--webport', str(web_port), '--introducer', introducer_furl, '--hide-ip', - '--tor-control-port', 'tcp:localhost:{}'.format(control_port), + '--tor-control-port', tor_network.client_control_endpoint, '--listen', 'tor', '--shares-needed', '1', '--shares-happy', '1', @@ -133,7 +132,7 @@ def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_ config = read_config(node_dir.path, "tub.port") config.set_config("tor", "onion", "true") config.set_config("tor", "onion.external_port", "3457") - config.set_config("tor", "control.port", f"tcp:port={control_port}:host=127.0.0.1") + config.set_config("tor", "control.port", tor_network.client_control_endpoint) config.set_config("tor", "onion.private_key_file", "private/tor_onion.privkey") print("running") @@ -159,7 +158,7 @@ def test_anonymous_client(reactor, request, temp_dir, flog_gatherer, tor_network ) yield util.await_client_ready(normie) - anonymoose = yield _create_anonymous_node(reactor, 'anonymoose', 8008, request, temp_dir, flog_gatherer, tor_network, introducer_furl, 1) + anonymoose = yield _create_anonymous_node(reactor, 'anonymoose', 8102, request, temp_dir, flog_gatherer, tor_network, introducer_furl, 1) yield util.await_client_ready(anonymoose, minimum_number_of_servers=1, timeout=600) yield upload_to_one_download_from_the_other(reactor, temp_dir, normie, anonymoose) diff --git a/integration/util.py b/integration/util.py index b614a84bd..909def8ef 100644 --- a/integration/util.py +++ b/integration/util.py @@ -659,7 +659,7 @@ def await_client_ready(tahoe, timeout=10, liveness=60*2, minimum_number_of_serve print( f"Now: {time.ctime()}\n" - f"Server last-received-data: {[time.ctime(s['last_received_data']) for s in servers]}" + f"Server last-received-data: {[s['last_received_data'] for s in servers]}" ) server_times = [