mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-19 03:06:33 +00:00
Merge remote-tracking branch 'origin/master' into 3575.realistic_storage_index_hash-key
This commit is contained in:
commit
af06bdb182
0
newsfragments/3384.minor
Normal file
0
newsfragments/3384.minor
Normal file
0
newsfragments/3529.minor
Normal file
0
newsfragments/3529.minor
Normal file
0
newsfragments/3564.minor
Normal file
0
newsfragments/3564.minor
Normal file
0
newsfragments/3572.minor
Normal file
0
newsfragments/3572.minor
Normal file
9
setup.py
9
setup.py
@ -111,7 +111,9 @@ install_requires = [
|
||||
|
||||
# Eliot is contemplating dropping Python 2 support. Stick to a version we
|
||||
# know works on Python 2.7.
|
||||
"eliot ~= 1.7",
|
||||
"eliot ~= 1.7 ; python_version < '3.0'",
|
||||
# On Python 3, we want a new enough version to support custom JSON encoders.
|
||||
"eliot >= 1.13.0 ; python_version > '3.0'",
|
||||
|
||||
# Pyrsistent 0.17.0 (which we use by way of Eliot) has dropped
|
||||
# Python 2 entirely; stick to the version known to work for us.
|
||||
@ -383,10 +385,7 @@ setup(name="tahoe-lafs", # also set in __init__.py
|
||||
# this version from time to time, but we will do it
|
||||
# intentionally.
|
||||
"pyflakes == 2.2.0",
|
||||
# coverage 5.0 breaks the integration tests in some opaque way.
|
||||
# This probably needs to be addressed in a more permanent way
|
||||
# eventually...
|
||||
"coverage ~= 4.5",
|
||||
"coverage ~= 5.0",
|
||||
"mock",
|
||||
"tox",
|
||||
"pytest",
|
||||
|
@ -669,8 +669,8 @@ def create_connection_handlers(config, i2p_provider, tor_provider):
|
||||
# create that handler, so hints which want it will be ignored.
|
||||
handlers = {
|
||||
"tcp": _make_tcp_handler(),
|
||||
"tor": tor_provider.get_tor_handler(),
|
||||
"i2p": i2p_provider.get_i2p_handler(),
|
||||
"tor": tor_provider.get_client_endpoint(),
|
||||
"i2p": i2p_provider.get_client_endpoint(),
|
||||
}
|
||||
log.msg(
|
||||
format="built Foolscap connection handlers for: %(known_handlers)s",
|
||||
|
@ -113,4 +113,5 @@ if sys.platform == "win32":
|
||||
initialize()
|
||||
|
||||
from eliot import to_file
|
||||
to_file(open("eliot.log", "w"))
|
||||
from allmydata.util.jsonbytes import BytesJSONEncoder
|
||||
to_file(open("eliot.log", "w"), encoder=BytesJSONEncoder)
|
||||
|
@ -31,6 +31,9 @@ from twisted.internet.defer import (
|
||||
maybeDeferred,
|
||||
)
|
||||
|
||||
from ..util.jsonbytes import BytesJSONEncoder
|
||||
|
||||
|
||||
_NAME = Field.for_types(
|
||||
u"name",
|
||||
[str],
|
||||
@ -61,6 +64,14 @@ def eliot_logged_test(f):
|
||||
class storage(object):
|
||||
pass
|
||||
|
||||
|
||||
# On Python 3, we want to use our custom JSON encoder when validating
|
||||
# messages can be encoded to JSON:
|
||||
if PY3:
|
||||
capture = lambda f : capture_logging(None, encoder_=BytesJSONEncoder)(f)
|
||||
else:
|
||||
capture = lambda f : capture_logging(None)(f)
|
||||
|
||||
@wraps(f)
|
||||
def run_and_republish(self, *a, **kw):
|
||||
# Unfortunately the only way to get at the global/default logger...
|
||||
@ -85,7 +96,7 @@ def eliot_logged_test(f):
|
||||
# can finish the test's action.
|
||||
storage.action.finish()
|
||||
|
||||
@capture_logging(None)
|
||||
@capture
|
||||
def run(self, logger):
|
||||
# Record the MemoryLogger for later message extraction.
|
||||
storage.logger = logger
|
||||
@ -165,9 +176,6 @@ class EliotLoggedRunTest(object):
|
||||
|
||||
@eliot_logged_test
|
||||
def run(self, result=None):
|
||||
# Workaround for https://github.com/itamarst/eliot/issues/456
|
||||
if PY3:
|
||||
self.case.eliot_logger._validate_message = lambda *args, **kwargs: None
|
||||
return self._run_tests_with_factory(
|
||||
self.case,
|
||||
self.handlers,
|
||||
|
@ -1,149 +1,69 @@
|
||||
import os
|
||||
import mock
|
||||
|
||||
from twisted.trial import unittest
|
||||
from twisted.internet import reactor, endpoints, defer
|
||||
from twisted.internet.interfaces import IStreamClientEndpoint
|
||||
from twisted.internet import reactor
|
||||
|
||||
from foolscap.connections import tcp
|
||||
|
||||
from testtools.matchers import (
|
||||
MatchesDict,
|
||||
IsInstance,
|
||||
Equals,
|
||||
)
|
||||
|
||||
from ..node import PrivacyError, config_from_string
|
||||
from ..node import create_connection_handlers
|
||||
from ..node import create_main_tub
|
||||
from ..util.i2p_provider import create as create_i2p_provider
|
||||
from ..util.tor_provider import create as create_tor_provider
|
||||
|
||||
from .common import (
|
||||
SyncTestCase,
|
||||
ConstantAddresses,
|
||||
)
|
||||
|
||||
|
||||
BASECONFIG = ""
|
||||
|
||||
|
||||
class TCP(unittest.TestCase):
|
||||
|
||||
def test_default(self):
|
||||
class CreateConnectionHandlersTests(SyncTestCase):
|
||||
"""
|
||||
Tests for the Foolscap connection handlers return by
|
||||
``create_connection_handlers``.
|
||||
"""
|
||||
def test_foolscap_handlers(self):
|
||||
"""
|
||||
``create_connection_handlers`` returns a Foolscap connection handlers
|
||||
dictionary mapping ``"tcp"`` to
|
||||
``foolscap.connections.tcp.DefaultTCP``, ``"tor"`` to the supplied Tor
|
||||
provider's handler, and ``"i2p"`` to the supplied I2P provider's
|
||||
handler.
|
||||
"""
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG,
|
||||
)
|
||||
_, foolscap_handlers = create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
self.assertIsInstance(
|
||||
foolscap_handlers['tcp'],
|
||||
tcp.DefaultTCP,
|
||||
tor_endpoint = object()
|
||||
tor = ConstantAddresses(handler=tor_endpoint)
|
||||
i2p_endpoint = object()
|
||||
i2p = ConstantAddresses(handler=i2p_endpoint)
|
||||
_, foolscap_handlers = create_connection_handlers(
|
||||
config,
|
||||
i2p,
|
||||
tor,
|
||||
)
|
||||
self.assertThat(
|
||||
foolscap_handlers,
|
||||
MatchesDict({
|
||||
"tcp": IsInstance(tcp.DefaultTCP),
|
||||
"i2p": Equals(i2p_endpoint),
|
||||
"tor": Equals(tor_endpoint),
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
class Tor(unittest.TestCase):
|
||||
|
||||
def test_disabled(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[tor]\nenabled = false\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertEqual(h, None)
|
||||
|
||||
def test_unimportable(self):
|
||||
with mock.patch("allmydata.util.tor_provider._import_tor",
|
||||
return_value=None):
|
||||
config = config_from_string("fake.port", "no-basedir", BASECONFIG)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertEqual(h, None)
|
||||
|
||||
def test_default(self):
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.default_socks",
|
||||
return_value=h1) as f:
|
||||
|
||||
config = config_from_string("fake.port", "no-basedir", BASECONFIG)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertEqual(f.mock_calls, [mock.call()])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def _do_test_launch(self, executable):
|
||||
# the handler is created right away
|
||||
config = BASECONFIG+"[tor]\nlaunch = true\n"
|
||||
if executable:
|
||||
config += "tor.executable = %s\n" % executable
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.control_endpoint_maker",
|
||||
return_value=h1) as f:
|
||||
|
||||
config = config_from_string("fake.port", ".", config)
|
||||
tp = create_tor_provider("reactor", config)
|
||||
h = tp.get_tor_handler()
|
||||
|
||||
private_dir = config.get_config_path("private")
|
||||
exp = mock.call(tp._make_control_endpoint,
|
||||
takes_status=True)
|
||||
self.assertEqual(f.mock_calls, [exp])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
# later, when Foolscap first connects, Tor should be launched
|
||||
reactor = "reactor"
|
||||
tcp = object()
|
||||
tcep = object()
|
||||
launch_tor = mock.Mock(return_value=defer.succeed(("ep_desc", tcp)))
|
||||
cfs = mock.Mock(return_value=tcep)
|
||||
with mock.patch("allmydata.util.tor_provider._launch_tor", launch_tor):
|
||||
with mock.patch("allmydata.util.tor_provider.clientFromString", cfs):
|
||||
d = tp._make_control_endpoint(reactor,
|
||||
update_status=lambda status: None)
|
||||
cep = self.successResultOf(d)
|
||||
launch_tor.assert_called_with(reactor, executable,
|
||||
os.path.abspath(private_dir),
|
||||
tp._txtorcon)
|
||||
cfs.assert_called_with(reactor, "ep_desc")
|
||||
self.assertIs(cep, tcep)
|
||||
|
||||
def test_launch(self):
|
||||
self._do_test_launch(None)
|
||||
|
||||
def test_launch_executable(self):
|
||||
self._do_test_launch("/special/tor")
|
||||
|
||||
def test_socksport_unix_endpoint(self):
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
||||
return_value=h1) as f:
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[tor]\nsocks.port = unix:/var/lib/fw-daemon/tor_socks.socket\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0][1][0]))
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_socksport_endpoint(self):
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
||||
return_value=h1) as f:
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[tor]\nsocks.port = tcp:127.0.0.1:1234\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0][1][0]))
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_socksport_endpoint_otherhost(self):
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
||||
return_value=h1) as f:
|
||||
config = config_from_string(
|
||||
"no-basedir",
|
||||
"fake.port",
|
||||
BASECONFIG + "[tor]\nsocks.port = tcp:otherhost:1234\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0][1][0]))
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_socksport_bad_endpoint(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
@ -176,73 +96,8 @@ class Tor(unittest.TestCase):
|
||||
str(ctx.exception)
|
||||
)
|
||||
|
||||
def test_controlport(self):
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.tor.control_endpoint",
|
||||
return_value=h1) as f:
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[tor]\ncontrol.port = tcp:localhost:1234\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(reactor, config)
|
||||
h = tor_provider.get_tor_handler()
|
||||
self.assertEqual(len(f.mock_calls), 1)
|
||||
ep = f.mock_calls[0][1][0]
|
||||
self.assertIsInstance(ep, endpoints.TCP4ClientEndpoint)
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
class I2P(unittest.TestCase):
|
||||
|
||||
def test_disabled(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\nenabled = false\n",
|
||||
)
|
||||
i2p_provider = create_i2p_provider(None, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
self.assertEqual(h, None)
|
||||
|
||||
def test_unimportable(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG,
|
||||
)
|
||||
with mock.patch("allmydata.util.i2p_provider._import_i2p",
|
||||
return_value=None):
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
self.assertEqual(h, None)
|
||||
|
||||
def test_default(self):
|
||||
config = config_from_string("fake.port", "no-basedir", BASECONFIG)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.default",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
self.assertEqual(f.mock_calls, [mock.call(reactor, keyfile=None)])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_samport(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\nsam.port = tcp:localhost:1234\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.sam_endpoint",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
|
||||
self.assertEqual(len(f.mock_calls), 1)
|
||||
ep = f.mock_calls[0][1][0]
|
||||
self.assertIsInstance(ep, endpoints.TCP4ClientEndpoint)
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_samport_and_launch(self):
|
||||
config = config_from_string(
|
||||
"no-basedir",
|
||||
@ -258,82 +113,6 @@ class I2P(unittest.TestCase):
|
||||
str(ctx.exception)
|
||||
)
|
||||
|
||||
def test_launch(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\nlaunch = true\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.launch",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
exp = mock.call(i2p_configdir=None, i2p_binary=None)
|
||||
self.assertEqual(f.mock_calls, [exp])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_launch_executable(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\nlaunch = true\n" + "i2p.executable = i2p\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.launch",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
exp = mock.call(i2p_configdir=None, i2p_binary="i2p")
|
||||
self.assertEqual(f.mock_calls, [exp])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_launch_configdir(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\nlaunch = true\n" + "i2p.configdir = cfg\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.launch",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
exp = mock.call(i2p_configdir="cfg", i2p_binary=None)
|
||||
self.assertEqual(f.mock_calls, [exp])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_launch_configdir_and_executable(self):
|
||||
config = config_from_string(
|
||||
"no-basedir",
|
||||
"fake.port",
|
||||
BASECONFIG + "[i2p]\nlaunch = true\n" +
|
||||
"i2p.executable = i2p\n" + "i2p.configdir = cfg\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.launch",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(reactor, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
exp = mock.call(i2p_configdir="cfg", i2p_binary="i2p")
|
||||
self.assertEqual(f.mock_calls, [exp])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
def test_configdir(self):
|
||||
config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[i2p]\ni2p.configdir = cfg\n",
|
||||
)
|
||||
h1 = mock.Mock()
|
||||
with mock.patch("foolscap.connections.i2p.local_i2p",
|
||||
return_value=h1) as f:
|
||||
i2p_provider = create_i2p_provider(None, config)
|
||||
h = i2p_provider.get_i2p_handler()
|
||||
|
||||
self.assertEqual(f.mock_calls, [mock.call("cfg")])
|
||||
self.assertIdentical(h, h1)
|
||||
|
||||
class Connections(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -341,7 +120,11 @@ class Connections(unittest.TestCase):
|
||||
self.config = config_from_string("fake.port", self.basedir, BASECONFIG)
|
||||
|
||||
def test_default(self):
|
||||
default_connection_handlers, _ = create_connection_handlers(self.config, mock.Mock(), mock.Mock())
|
||||
default_connection_handlers, _ = create_connection_handlers(
|
||||
self.config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
self.assertEqual(default_connection_handlers["tcp"], "tcp")
|
||||
self.assertEqual(default_connection_handlers["tor"], "tor")
|
||||
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
||||
@ -352,23 +135,39 @@ class Connections(unittest.TestCase):
|
||||
"no-basedir",
|
||||
BASECONFIG + "[connections]\ntcp = tor\n",
|
||||
)
|
||||
default_connection_handlers, _ = create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
default_connection_handlers, _ = create_connection_handlers(
|
||||
config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
|
||||
self.assertEqual(default_connection_handlers["tcp"], "tor")
|
||||
self.assertEqual(default_connection_handlers["tor"], "tor")
|
||||
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
||||
|
||||
def test_tor_unimportable(self):
|
||||
with mock.patch("allmydata.util.tor_provider._import_tor",
|
||||
return_value=None):
|
||||
"""
|
||||
If the configuration calls for substituting Tor for TCP and
|
||||
``foolscap.connections.tor`` is not importable then
|
||||
``create_connection_handlers`` raises ``ValueError`` with a message
|
||||
explaining this makes Tor unusable.
|
||||
"""
|
||||
self.config = config_from_string(
|
||||
"fake.port",
|
||||
"no-basedir",
|
||||
BASECONFIG + "[connections]\ntcp = tor\n",
|
||||
)
|
||||
tor_provider = create_tor_provider(
|
||||
reactor,
|
||||
self.config,
|
||||
import_tor=lambda: None,
|
||||
)
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
tor_provider = create_tor_provider(reactor, self.config)
|
||||
default_connection_handlers, _ = create_connection_handlers(self.config, mock.Mock(), tor_provider)
|
||||
default_connection_handlers, _ = create_connection_handlers(
|
||||
self.config,
|
||||
i2p_provider=ConstantAddresses(handler=object()),
|
||||
tor_provider=tor_provider,
|
||||
)
|
||||
self.assertEqual(
|
||||
str(ctx.exception),
|
||||
"'tahoe.cfg [connections] tcp='"
|
||||
@ -383,7 +182,11 @@ class Connections(unittest.TestCase):
|
||||
BASECONFIG + "[connections]\ntcp = unknown\n",
|
||||
)
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
create_connection_handlers(
|
||||
config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
self.assertIn("'tahoe.cfg [connections] tcp='", str(ctx.exception))
|
||||
self.assertIn("uses unknown handler type 'unknown'", str(ctx.exception))
|
||||
|
||||
@ -393,7 +196,11 @@ class Connections(unittest.TestCase):
|
||||
"no-basedir",
|
||||
BASECONFIG + "[connections]\ntcp = disabled\n",
|
||||
)
|
||||
default_connection_handlers, _ = create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
default_connection_handlers, _ = create_connection_handlers(
|
||||
config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
self.assertEqual(default_connection_handlers["tcp"], None)
|
||||
self.assertEqual(default_connection_handlers["tor"], "tor")
|
||||
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
||||
@ -408,7 +215,11 @@ class Privacy(unittest.TestCase):
|
||||
)
|
||||
|
||||
with self.assertRaises(PrivacyError) as ctx:
|
||||
create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
create_connection_handlers(
|
||||
config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
str(ctx.exception),
|
||||
@ -423,7 +234,11 @@ class Privacy(unittest.TestCase):
|
||||
BASECONFIG + "[connections]\ntcp = disabled\n" +
|
||||
"[node]\nreveal-IP-address = false\n",
|
||||
)
|
||||
default_connection_handlers, _ = create_connection_handlers(config, mock.Mock(), mock.Mock())
|
||||
default_connection_handlers, _ = create_connection_handlers(
|
||||
config,
|
||||
ConstantAddresses(handler=object()),
|
||||
ConstantAddresses(handler=object()),
|
||||
)
|
||||
self.assertEqual(default_connection_handlers["tcp"], None)
|
||||
|
||||
def test_tub_location_auto(self):
|
||||
@ -434,7 +249,14 @@ class Privacy(unittest.TestCase):
|
||||
)
|
||||
|
||||
with self.assertRaises(PrivacyError) as ctx:
|
||||
create_main_tub(config, {}, {}, {}, mock.Mock(), mock.Mock())
|
||||
create_main_tub(
|
||||
config,
|
||||
tub_options={},
|
||||
default_connection_handlers={},
|
||||
foolscap_connection_handlers={},
|
||||
i2p_provider=ConstantAddresses(),
|
||||
tor_provider=ConstantAddresses(),
|
||||
)
|
||||
self.assertEqual(
|
||||
str(ctx.exception),
|
||||
"tub.location uses AUTO",
|
||||
|
@ -57,11 +57,14 @@ from ..util.eliotutil import (
|
||||
_parse_destination_description,
|
||||
_EliotLogging,
|
||||
)
|
||||
from ..util.jsonbytes import BytesJSONEncoder
|
||||
|
||||
from .common import (
|
||||
SyncTestCase,
|
||||
AsyncTestCase,
|
||||
)
|
||||
|
||||
|
||||
class EliotLoggedTestTests(AsyncTestCase):
|
||||
def test_returns_none(self):
|
||||
Message.log(hello="world")
|
||||
@ -94,7 +97,7 @@ class ParseDestinationDescriptionTests(SyncTestCase):
|
||||
reactor = object()
|
||||
self.assertThat(
|
||||
_parse_destination_description("file:-")(reactor),
|
||||
Equals(FileDestination(stdout)),
|
||||
Equals(FileDestination(stdout, encoder=BytesJSONEncoder)),
|
||||
)
|
||||
|
||||
|
||||
|
@ -277,6 +277,20 @@ class Provider(unittest.TestCase):
|
||||
i2p.local_i2p.assert_called_with("configdir")
|
||||
self.assertIs(h, handler)
|
||||
|
||||
def test_handler_launch_executable(self):
|
||||
i2p = mock.Mock()
|
||||
handler = object()
|
||||
i2p.launch = mock.Mock(return_value=handler)
|
||||
reactor = object()
|
||||
|
||||
with mock_i2p(i2p):
|
||||
p = i2p_provider.create(reactor,
|
||||
FakeConfig(launch=True,
|
||||
**{"i2p.executable": "myi2p"}))
|
||||
h = p.get_i2p_handler()
|
||||
self.assertIs(h, handler)
|
||||
i2p.launch.assert_called_with(i2p_configdir=None, i2p_binary="myi2p")
|
||||
|
||||
def test_handler_default(self):
|
||||
i2p = mock.Mock()
|
||||
handler = object()
|
||||
|
@ -2327,7 +2327,8 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||
files.append(fn)
|
||||
data = "data to be uploaded: file%d\n" % i
|
||||
datas.append(data)
|
||||
open(fn,"wb").write(data)
|
||||
with open(fn, "wb") as f:
|
||||
f.write(data)
|
||||
|
||||
def _check_stdout_against(out_and_err, filenum=None, data=None):
|
||||
(out, err) = out_and_err
|
||||
@ -2505,13 +2506,18 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||
# recursive copy: setup
|
||||
dn = os.path.join(self.basedir, "dir1")
|
||||
os.makedirs(dn)
|
||||
open(os.path.join(dn, "rfile1"), "wb").write("rfile1")
|
||||
open(os.path.join(dn, "rfile2"), "wb").write("rfile2")
|
||||
open(os.path.join(dn, "rfile3"), "wb").write("rfile3")
|
||||
with open(os.path.join(dn, "rfile1"), "wb") as f:
|
||||
f.write("rfile1")
|
||||
with open(os.path.join(dn, "rfile2"), "wb") as f:
|
||||
f.write("rfile2")
|
||||
with open(os.path.join(dn, "rfile3"), "wb") as f:
|
||||
f.write("rfile3")
|
||||
sdn2 = os.path.join(dn, "subdir2")
|
||||
os.makedirs(sdn2)
|
||||
open(os.path.join(sdn2, "rfile4"), "wb").write("rfile4")
|
||||
open(os.path.join(sdn2, "rfile5"), "wb").write("rfile5")
|
||||
with open(os.path.join(sdn2, "rfile4"), "wb") as f:
|
||||
f.write("rfile4")
|
||||
with open(os.path.join(sdn2, "rfile5"), "wb") as f:
|
||||
f.write("rfile5")
|
||||
|
||||
# from disk into tahoe
|
||||
d.addCallback(run, "cp", "-r", dn, "tahoe:")
|
||||
|
@ -349,6 +349,10 @@ class Provider(unittest.TestCase):
|
||||
cfs2.assert_called_with(reactor, ep_desc)
|
||||
|
||||
def test_handler_socks_endpoint(self):
|
||||
"""
|
||||
If not configured otherwise, the Tor provider returns a Socks-based
|
||||
handler.
|
||||
"""
|
||||
tor = mock.Mock()
|
||||
handler = object()
|
||||
tor.socks_endpoint = mock.Mock(return_value=handler)
|
||||
@ -365,6 +369,46 @@ class Provider(unittest.TestCase):
|
||||
tor.socks_endpoint.assert_called_with(ep)
|
||||
self.assertIs(h, handler)
|
||||
|
||||
def test_handler_socks_unix_endpoint(self):
|
||||
"""
|
||||
``socks.port`` can be configured as a UNIX client endpoint.
|
||||
"""
|
||||
tor = mock.Mock()
|
||||
handler = object()
|
||||
tor.socks_endpoint = mock.Mock(return_value=handler)
|
||||
ep = object()
|
||||
cfs = mock.Mock(return_value=ep)
|
||||
reactor = object()
|
||||
|
||||
with mock_tor(tor):
|
||||
p = tor_provider.create(reactor,
|
||||
FakeConfig(**{"socks.port": "unix:path"}))
|
||||
with mock.patch("allmydata.util.tor_provider.clientFromString", cfs):
|
||||
h = p.get_tor_handler()
|
||||
cfs.assert_called_with(reactor, "unix:path")
|
||||
tor.socks_endpoint.assert_called_with(ep)
|
||||
self.assertIs(h, handler)
|
||||
|
||||
def test_handler_socks_tcp_endpoint(self):
|
||||
"""
|
||||
``socks.port`` can be configured as a UNIX client endpoint.
|
||||
"""
|
||||
tor = mock.Mock()
|
||||
handler = object()
|
||||
tor.socks_endpoint = mock.Mock(return_value=handler)
|
||||
ep = object()
|
||||
cfs = mock.Mock(return_value=ep)
|
||||
reactor = object()
|
||||
|
||||
with mock_tor(tor):
|
||||
p = tor_provider.create(reactor,
|
||||
FakeConfig(**{"socks.port": "tcp:127.0.0.1:1234"}))
|
||||
with mock.patch("allmydata.util.tor_provider.clientFromString", cfs):
|
||||
h = p.get_tor_handler()
|
||||
cfs.assert_called_with(reactor, "tcp:127.0.0.1:1234")
|
||||
tor.socks_endpoint.assert_called_with(ep)
|
||||
self.assertIs(h, handler)
|
||||
|
||||
def test_handler_control_endpoint(self):
|
||||
tor = mock.Mock()
|
||||
handler = object()
|
||||
|
@ -86,6 +86,9 @@ from twisted.internet.defer import (
|
||||
)
|
||||
from twisted.application.service import Service
|
||||
|
||||
from .jsonbytes import BytesJSONEncoder
|
||||
|
||||
|
||||
def validateInstanceOf(t):
|
||||
"""
|
||||
Return an Eliot validator that requires values to be instances of ``t``.
|
||||
@ -302,7 +305,7 @@ class _DestinationParser(object):
|
||||
rotateLength=rotate_length,
|
||||
maxRotatedFiles=max_rotated_files,
|
||||
)
|
||||
return lambda reactor: FileDestination(get_file())
|
||||
return lambda reactor: FileDestination(get_file(), BytesJSONEncoder)
|
||||
|
||||
|
||||
_parse_destination_description = _DestinationParser().parse
|
||||
|
@ -17,23 +17,7 @@ from ..interfaces import (
|
||||
IAddressFamily,
|
||||
)
|
||||
|
||||
def create(reactor, config):
|
||||
"""
|
||||
Create a new _Provider service (this is an IService so must be
|
||||
hooked up to a parent or otherwise started).
|
||||
|
||||
If foolscap.connections.tor or txtorcon are not installed, then
|
||||
Provider.get_tor_handler() will return None. If tahoe.cfg wants
|
||||
to start an onion service too, then this `create()` method will
|
||||
throw a nice error (and startService will throw an ugly error).
|
||||
"""
|
||||
provider = _Provider(config, reactor)
|
||||
provider.check_onion_config()
|
||||
return provider
|
||||
|
||||
|
||||
def _import_tor():
|
||||
# this exists to be overridden by unit tests
|
||||
try:
|
||||
from foolscap.connections import tor
|
||||
return tor
|
||||
@ -47,6 +31,25 @@ def _import_txtorcon():
|
||||
except ImportError: # pragma: no cover
|
||||
return None
|
||||
|
||||
def create(reactor, config, import_tor=None, import_txtorcon=None):
|
||||
"""
|
||||
Create a new _Provider service (this is an IService so must be
|
||||
hooked up to a parent or otherwise started).
|
||||
|
||||
If foolscap.connections.tor or txtorcon are not installed, then
|
||||
Provider.get_tor_handler() will return None. If tahoe.cfg wants
|
||||
to start an onion service too, then this `create()` method will
|
||||
throw a nice error (and startService will throw an ugly error).
|
||||
"""
|
||||
if import_tor is None:
|
||||
import_tor = _import_tor
|
||||
if import_txtorcon is None:
|
||||
import_txtorcon = _import_txtorcon
|
||||
provider = _Provider(config, reactor, import_tor(), import_txtorcon())
|
||||
provider.check_onion_config()
|
||||
return provider
|
||||
|
||||
|
||||
def data_directory(private_dir):
|
||||
return os.path.join(private_dir, "tor-statedir")
|
||||
|
||||
@ -217,14 +220,14 @@ def create_config(reactor, cli_config):
|
||||
|
||||
@implementer(IAddressFamily)
|
||||
class _Provider(service.MultiService):
|
||||
def __init__(self, config, reactor):
|
||||
def __init__(self, config, reactor, tor, txtorcon):
|
||||
service.MultiService.__init__(self)
|
||||
self._config = config
|
||||
self._tor_launched = None
|
||||
self._onion_ehs = None
|
||||
self._onion_tor_control_proto = None
|
||||
self._tor = _import_tor()
|
||||
self._txtorcon = _import_txtorcon()
|
||||
self._tor = tor
|
||||
self._txtorcon = txtorcon
|
||||
self._reactor = reactor
|
||||
|
||||
def _get_tor_config(self, *args, **kwargs):
|
||||
|
Loading…
Reference in New Issue
Block a user