Merge remote-tracking branch 'origin/master' into clean-up-tor-and-i2p-providers

This commit is contained in:
Jean-Paul Calderone 2023-04-05 08:37:58 -04:00
commit 7cd0c9d724
9 changed files with 84 additions and 124 deletions

View File

@ -150,7 +150,8 @@ def flog_gatherer(reactor, temp_dir, flog_binary, request):
'--location', 'tcp:localhost:3117', '--location', 'tcp:localhost:3117',
'--port', '3117', '--port', '3117',
gather_dir, gather_dir,
) ),
env=environ,
) )
pytest_twisted.blockon(out_protocol.done) pytest_twisted.blockon(out_protocol.done)
@ -163,6 +164,7 @@ def flog_gatherer(reactor, temp_dir, flog_binary, request):
join(gather_dir, 'gatherer.tac'), join(gather_dir, 'gatherer.tac'),
), ),
path=gather_dir, path=gather_dir,
env=environ,
) )
pytest_twisted.blockon(twistd_protocol.magic_seen) pytest_twisted.blockon(twistd_protocol.magic_seen)
@ -181,6 +183,7 @@ def flog_gatherer(reactor, temp_dir, flog_binary, request):
( (
'flogtool', 'dump', join(temp_dir, 'flog_gather', flogs[0]) 'flogtool', 'dump', join(temp_dir, 'flog_gather', flogs[0])
), ),
env=environ,
) )
print("Waiting for flogtool to complete") print("Waiting for flogtool to complete")
try: try:

View File

@ -2,26 +2,11 @@
Integration tests for I2P support. Integration tests for I2P support.
""" """
from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from future.utils import PY2
if PY2:
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import sys import sys
from os.path import join, exists from os.path import join, exists
from os import mkdir from os import mkdir, environ
from time import sleep from time import sleep
from shutil import which
if PY2:
def which(path):
# This will result in skipping I2P tests on Python 2. Oh well.
return None
else:
from shutil import which
from eliot import log_call from eliot import log_call
@ -62,6 +47,7 @@ def i2p_network(reactor, temp_dir, request):
"--log=stdout", "--log=stdout",
"--loglevel=info" "--loglevel=info"
), ),
env=environ,
) )
def cleanup(): def cleanup():
@ -170,7 +156,8 @@ def test_i2p_service_storage(reactor, request, temp_dir, flog_gatherer, i2p_netw
sys.executable, '-b', '-m', 'allmydata.scripts.runner', sys.executable, '-b', '-m', 'allmydata.scripts.runner',
'-d', join(temp_dir, 'carol_i2p'), '-d', join(temp_dir, 'carol_i2p'),
'put', gold_path, 'put', gold_path,
) ),
env=environ,
) )
yield proto.done yield proto.done
cap = proto.output.getvalue().strip().split()[-1] cap = proto.output.getvalue().strip().split()[-1]
@ -184,7 +171,8 @@ def test_i2p_service_storage(reactor, request, temp_dir, flog_gatherer, i2p_netw
sys.executable, '-b', '-m', 'allmydata.scripts.runner', sys.executable, '-b', '-m', 'allmydata.scripts.runner',
'-d', join(temp_dir, 'dave_i2p'), '-d', join(temp_dir, 'dave_i2p'),
'get', cap, 'get', cap,
) ),
env=environ,
) )
yield proto.done yield proto.done
@ -211,7 +199,8 @@ def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_
'--hide-ip', '--hide-ip',
'--listen', 'i2p', '--listen', 'i2p',
node_dir.path, node_dir.path,
) ),
env=environ,
) )
yield proto.done yield proto.done

View File

@ -1,17 +1,10 @@
""" """
Ported to Python 3. Ported to Python 3.
""" """
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future.utils import PY2
if PY2:
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import sys import sys
from os.path import join from os.path import join
from os import environ
from twisted.internet.error import ProcessTerminated from twisted.internet.error import ProcessTerminated
@ -45,7 +38,8 @@ def test_upload_immutable(reactor, temp_dir, introducer_furl, flog_gatherer, sto
sys.executable, '-b', '-m', 'allmydata.scripts.runner', sys.executable, '-b', '-m', 'allmydata.scripts.runner',
'-d', node_dir, '-d', node_dir,
'put', __file__, 'put', __file__,
] ],
env=environ,
) )
try: try:
yield proto.done yield proto.done

View File

@ -1,17 +1,10 @@
""" """
Ported to Python 3. Ported to Python 3.
""" """
from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from future.utils import PY2
if PY2:
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import sys import sys
from os.path import join from os.path import join
from os import environ
import pytest import pytest
import pytest_twisted import pytest_twisted
@ -35,9 +28,6 @@ from allmydata.test.common import (
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
pytest.skip('Skipping Tor tests on Windows', allow_module_level=True) pytest.skip('Skipping Tor tests on Windows', allow_module_level=True)
if PY2:
pytest.skip('Skipping Tor tests on Python 2 because dependencies are hard to come by', allow_module_level=True)
@pytest_twisted.inlineCallbacks @pytest_twisted.inlineCallbacks
def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl): def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl):
carol = yield _create_anonymous_node(reactor, 'carol', 8008, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl) carol = yield _create_anonymous_node(reactor, 'carol', 8008, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl)
@ -65,7 +55,8 @@ def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_ne
sys.executable, '-b', '-m', 'allmydata.scripts.runner', sys.executable, '-b', '-m', 'allmydata.scripts.runner',
'-d', join(temp_dir, 'carol'), '-d', join(temp_dir, 'carol'),
'put', gold_path, 'put', gold_path,
) ),
env=environ,
) )
yield proto.done yield proto.done
cap = proto.output.getvalue().strip().split()[-1] cap = proto.output.getvalue().strip().split()[-1]
@ -79,7 +70,8 @@ def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_ne
sys.executable, '-b', '-m', 'allmydata.scripts.runner', sys.executable, '-b', '-m', 'allmydata.scripts.runner',
'-d', join(temp_dir, 'dave'), '-d', join(temp_dir, 'dave'),
'get', cap, 'get', cap,
) ),
env=environ,
) )
yield proto.done yield proto.done
@ -108,7 +100,8 @@ def _create_anonymous_node(reactor, name, control_port, request, temp_dir, flog_
'--tor-control-port', 'tcp:localhost:{}'.format(control_port), '--tor-control-port', 'tcp:localhost:{}'.format(control_port),
'--listen', 'tor', '--listen', 'tor',
node_dir.path, node_dir.path,
) ),
env=environ,
) )
yield proto.done yield proto.done

View File

@ -9,7 +9,7 @@ no_implicit_optional = True
warn_redundant_casts = True warn_redundant_casts = True
strict_equality = True strict_equality = True
[mypy-allmydata.test.cli.wormholetesting,allmydata.listeners] [mypy-allmydata.test.cli.wormholetesting,allmydata.listeners,allmydata.test.test_connection_status]
disallow_any_generics = True disallow_any_generics = True
disallow_subclassing_any = True disallow_subclassing_any = True
disallow_untyped_calls = True disallow_untyped_calls = True

0
newsfragments/4001.minor Normal file
View File

0
newsfragments/4003.minor Normal file
View File

View File

@ -1,25 +1,46 @@
""" """
Tests for allmydata.util.connection_status. Tests for allmydata.util.connection_status.
Port to Python 3.
""" """
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future.utils import PY2 from __future__ import annotations
if PY2:
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import mock from typing import Optional
from twisted.trial import unittest from foolscap.reconnector import ReconnectionInfo, Reconnector
from foolscap.info import ConnectionInfo
from ..util import connection_status from ..util import connection_status
from .common import SyncTestCase
class Status(unittest.TestCase): def reconnector(info: ReconnectionInfo) -> Reconnector:
def test_hint_statuses(self): rc = Reconnector(None, None, (), {}) # type: ignore[no-untyped-call]
rc._reconnectionInfo = info
return rc
def connection_info(
statuses: dict[str, str],
handlers: dict[str, str],
winningHint: Optional[str],
establishedAt: Optional[int],
) -> ConnectionInfo:
ci = ConnectionInfo() # type: ignore[no-untyped-call]
ci.connectorStatuses = statuses
ci.connectionHandlers = handlers
ci.winningHint = winningHint
ci.establishedAt = establishedAt
return ci
def reconnection_info(
state: str,
connection_info: ConnectionInfo,
) -> ReconnectionInfo:
ri = ReconnectionInfo() # type: ignore[no-untyped-call]
ri.state = state
ri.connectionInfo = connection_info
return ri
class Status(SyncTestCase):
def test_hint_statuses(self) -> None:
ncs = connection_status._hint_statuses(["h2","h1"], ncs = connection_status._hint_statuses(["h2","h1"],
{"h1": "hand1", "h4": "hand4"}, {"h1": "hand1", "h4": "hand4"},
{"h1": "st1", "h2": "st2", {"h1": "st1", "h2": "st2",
@ -27,17 +48,10 @@ class Status(unittest.TestCase):
self.assertEqual(ncs, {"h1 via hand1": "st1", self.assertEqual(ncs, {"h1 via hand1": "st1",
"h2": "st2"}) "h2": "st2"})
def test_reconnector_connected(self): def test_reconnector_connected(self) -> None:
ci = mock.Mock() ci = connection_info({"h1": "st1"}, {"h1": "hand1"}, "h1", 120)
ci.connectorStatuses = {"h1": "st1"} ri = reconnection_info("connected", ci)
ci.connectionHandlers = {"h1": "hand1"} rc = reconnector(ri)
ci.winningHint = "h1"
ci.establishedAt = 120
ri = mock.Mock()
ri.state = "connected"
ri.connectionInfo = ci
rc = mock.Mock
rc.getReconnectionInfo = mock.Mock(return_value=ri)
cs = connection_status.from_foolscap_reconnector(rc, 123) cs = connection_status.from_foolscap_reconnector(rc, 123)
self.assertEqual(cs.connected, True) self.assertEqual(cs.connected, True)
self.assertEqual(cs.summary, "Connected to h1 via hand1") self.assertEqual(cs.summary, "Connected to h1 via hand1")
@ -45,17 +59,10 @@ class Status(unittest.TestCase):
self.assertEqual(cs.last_connection_time, 120) self.assertEqual(cs.last_connection_time, 120)
self.assertEqual(cs.last_received_time, 123) self.assertEqual(cs.last_received_time, 123)
def test_reconnector_connected_others(self): def test_reconnector_connected_others(self) -> None:
ci = mock.Mock() ci = connection_info({"h1": "st1", "h2": "st2"}, {"h1": "hand1"}, "h1", 120)
ci.connectorStatuses = {"h1": "st1", "h2": "st2"} ri = reconnection_info("connected", ci)
ci.connectionHandlers = {"h1": "hand1"} rc = reconnector(ri)
ci.winningHint = "h1"
ci.establishedAt = 120
ri = mock.Mock()
ri.state = "connected"
ri.connectionInfo = ci
rc = mock.Mock
rc.getReconnectionInfo = mock.Mock(return_value=ri)
cs = connection_status.from_foolscap_reconnector(rc, 123) cs = connection_status.from_foolscap_reconnector(rc, 123)
self.assertEqual(cs.connected, True) self.assertEqual(cs.connected, True)
self.assertEqual(cs.summary, "Connected to h1 via hand1") self.assertEqual(cs.summary, "Connected to h1 via hand1")
@ -63,18 +70,11 @@ class Status(unittest.TestCase):
self.assertEqual(cs.last_connection_time, 120) self.assertEqual(cs.last_connection_time, 120)
self.assertEqual(cs.last_received_time, 123) self.assertEqual(cs.last_received_time, 123)
def test_reconnector_connected_listener(self): def test_reconnector_connected_listener(self) -> None:
ci = mock.Mock() ci = connection_info({"h1": "st1", "h2": "st2"}, {"h1": "hand1"}, None, 120)
ci.connectorStatuses = {"h1": "st1", "h2": "st2"}
ci.connectionHandlers = {"h1": "hand1"}
ci.listenerStatus = ("listener1", "successful") ci.listenerStatus = ("listener1", "successful")
ci.winningHint = None ri = reconnection_info("connected", ci)
ci.establishedAt = 120 rc = reconnector(ri)
ri = mock.Mock()
ri.state = "connected"
ri.connectionInfo = ci
rc = mock.Mock
rc.getReconnectionInfo = mock.Mock(return_value=ri)
cs = connection_status.from_foolscap_reconnector(rc, 123) cs = connection_status.from_foolscap_reconnector(rc, 123)
self.assertEqual(cs.connected, True) self.assertEqual(cs.connected, True)
self.assertEqual(cs.summary, "Connected via listener (listener1)") self.assertEqual(cs.summary, "Connected via listener (listener1)")
@ -83,15 +83,10 @@ class Status(unittest.TestCase):
self.assertEqual(cs.last_connection_time, 120) self.assertEqual(cs.last_connection_time, 120)
self.assertEqual(cs.last_received_time, 123) self.assertEqual(cs.last_received_time, 123)
def test_reconnector_connecting(self): def test_reconnector_connecting(self) -> None:
ci = mock.Mock() ci = connection_info({"h1": "st1", "h2": "st2"}, {"h1": "hand1"}, None, None)
ci.connectorStatuses = {"h1": "st1", "h2": "st2"} ri = reconnection_info("connecting", ci)
ci.connectionHandlers = {"h1": "hand1"} rc = reconnector(ri)
ri = mock.Mock()
ri.state = "connecting"
ri.connectionInfo = ci
rc = mock.Mock
rc.getReconnectionInfo = mock.Mock(return_value=ri)
cs = connection_status.from_foolscap_reconnector(rc, 123) cs = connection_status.from_foolscap_reconnector(rc, 123)
self.assertEqual(cs.connected, False) self.assertEqual(cs.connected, False)
self.assertEqual(cs.summary, "Trying to connect") self.assertEqual(cs.summary, "Trying to connect")
@ -100,19 +95,13 @@ class Status(unittest.TestCase):
self.assertEqual(cs.last_connection_time, None) self.assertEqual(cs.last_connection_time, None)
self.assertEqual(cs.last_received_time, 123) self.assertEqual(cs.last_received_time, 123)
def test_reconnector_waiting(self): def test_reconnector_waiting(self) -> None:
ci = mock.Mock() ci = connection_info({"h1": "st1", "h2": "st2"}, {"h1": "hand1"}, None, None)
ci.connectorStatuses = {"h1": "st1", "h2": "st2"} ri = reconnection_info("waiting", ci)
ci.connectionHandlers = {"h1": "hand1"}
ri = mock.Mock()
ri.state = "waiting"
ri.lastAttempt = 10 ri.lastAttempt = 10
ri.nextAttempt = 20 ri.nextAttempt = 20
ri.connectionInfo = ci rc = reconnector(ri)
rc = mock.Mock cs = connection_status.from_foolscap_reconnector(rc, 5, time=lambda: 12)
rc.getReconnectionInfo = mock.Mock(return_value=ri)
with mock.patch("time.time", return_value=12):
cs = connection_status.from_foolscap_reconnector(rc, 5)
self.assertEqual(cs.connected, False) self.assertEqual(cs.connected, False)
self.assertEqual(cs.summary, self.assertEqual(cs.summary,
"Reconnecting in 8 seconds (last attempt 2s ago)") "Reconnecting in 8 seconds (last attempt 2s ago)")

View File

@ -1,21 +1,13 @@
""" """
Parse connection status from Foolscap. Parse connection status from Foolscap.
Ported to Python 3.
""" """
from __future__ import absolute_import from __future__ import annotations
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future.utils import PY2
if PY2:
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import time import time
from zope.interface import implementer from zope.interface import implementer
from ..interfaces import IConnectionStatus from ..interfaces import IConnectionStatus
from foolscap.reconnector import Reconnector
@implementer(IConnectionStatus) @implementer(IConnectionStatus)
class ConnectionStatus(object): class ConnectionStatus(object):
@ -41,7 +33,7 @@ class ConnectionStatus(object):
last_received_time=None, last_received_time=None,
) )
def _hint_statuses(which, handlers, statuses): def _hint_statuses(which, handlers, statuses) -> dict[str, str]:
non_connected_statuses = {} non_connected_statuses = {}
for hint in which: for hint in which:
handler = handlers.get(hint) handler = handlers.get(hint)
@ -50,7 +42,7 @@ def _hint_statuses(which, handlers, statuses):
non_connected_statuses["%s%s" % (hint, handler_dsc)] = dsc non_connected_statuses["%s%s" % (hint, handler_dsc)] = dsc
return non_connected_statuses return non_connected_statuses
def from_foolscap_reconnector(rc, last_received): def from_foolscap_reconnector(rc: Reconnector, last_received: int, time=time.time) -> ConnectionStatus:
ri = rc.getReconnectionInfo() ri = rc.getReconnectionInfo()
# See foolscap/reconnector.py, ReconnectionInfo, for details about possible # See foolscap/reconnector.py, ReconnectionInfo, for details about possible
# states. The returned result is a native string, it seems, so convert to # states. The returned result is a native string, it seems, so convert to
@ -80,7 +72,7 @@ def from_foolscap_reconnector(rc, last_received):
# ci describes the current in-progress attempt # ci describes the current in-progress attempt
summary = "Trying to connect" summary = "Trying to connect"
elif state == "waiting": elif state == "waiting":
now = time.time() now = time()
elapsed = now - ri.lastAttempt elapsed = now - ri.lastAttempt
delay = ri.nextAttempt - now delay = ri.nextAttempt - now
summary = "Reconnecting in %d seconds (last attempt %ds ago)" % \ summary = "Reconnecting in %d seconds (last attempt %ds ago)" % \