more refactor + fix some node tests

This commit is contained in:
meejah
2018-01-28 01:27:25 -07:00
parent 71484b4a12
commit 43d857a0bd
5 changed files with 115 additions and 68 deletions

View File

@ -206,17 +206,21 @@ def create_client(basedir=u".", _client_factory=None):
config = read_config(basedir, u"client.port", _valid_config_sections=_valid_config_sections) config = read_config(basedir, u"client.port", _valid_config_sections=_valid_config_sections)
return create_client_from_config(basedir, config) return create_client_from_config(basedir, config)
# this can/should be async # this can/should be async
# @defer.inlineCallbacks # @defer.inlineCallbacks
def create_client_from_config(basedir, config): def create_client_from_config(basedir, config):
default_connection_handlers, foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config) from twisted.internet import reactor
from allmydata.node import create_i2p_provider, create_tor_provider
i2p_provider = create_i2p_provider(reactor, basedir, config)
tor_provider = create_tor_provider(reactor, basedir, config)
handlers = create_connection_handlers(reactor, basedir, config, i2p_provider, tor_provider)
default_connection_handlers, foolscap_connection_handlers = handlers
tub_options = create_tub_options(config) tub_options = create_tub_options(config)
i2p_provider = None
tor_provider = None
main_tub, is_listening = create_main_tub( main_tub, is_listening = create_main_tub(
basedir, config, tub_options, default_connection_handlers, basedir, config, tub_options, default_connection_handlers,
foolscap_connection_handlers, foolscap_connection_handlers, i2p_provider, tor_provider,
) )
control_tub = create_control_tub() control_tub = create_control_tub()
return defer.succeed( return defer.succeed(

View File

@ -47,14 +47,20 @@ def create_introducer(basedir=u"."):
_valid_config_sections=_valid_config_sections, _valid_config_sections=_valid_config_sections,
) )
default_connection_handlers, foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config) # XXX fix up imports etc (also: reactor)
from twisted.internet import reactor
from allmydata.node import create_i2p_provider, create_tor_provider
i2p_provider = create_i2p_provider(reactor, basedir, config)
tor_provider = create_tor_provider(reactor, basedir, config)
default_connection_handlers, foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config, i2p_provider, tor_provider)
tub_options = create_tub_options(config) tub_options = create_tub_options(config)
i2p_provider = None i2p_provider = None
tor_provider = None tor_provider = None
main_tub, is_listening = create_main_tub( main_tub, is_listening = create_main_tub(
basedir, config, tub_options, default_connection_handlers, basedir, config, tub_options, default_connection_handlers,
foolscap_connection_handlers, foolscap_connection_handlers, i2p_provider, tor_provider,
) )
control_tub = create_control_tub() control_tub = create_control_tub()

View File

@ -459,13 +459,11 @@ def _make_i2p_handler(i2p_provider):
return i2p_provider.get_i2p_handler() return i2p_provider.get_i2p_handler()
def create_connection_handlers(reactor, config): def create_connection_handlers(reactor, config, i2p_provider, tor_provider):
""" """
:returns: 2-tuple of default_connection_handlers, foolscap_connection_handlers :returns: 2-tuple of default_connection_handlers, foolscap_connection_handlers
""" """
reveal_ip = config.get_config("node", "reveal-IP-address", True, boolean=True) reveal_ip = config.get_config("node", "reveal-IP-address", True, boolean=True)
i2p_provider = create_i2p_provider(reactor, basedir, config)
tor_provider = create_tor_provider(reactor, basedir, config)
# We store handlers for everything. None means we were unable to # We store handlers for everything. None means we were unable to
# create that handler, so hints which want it will be ignored. # create that handler, so hints which want it will be ignored.
@ -625,8 +623,10 @@ def _tub_portlocation(config, cfg_tubport, cfg_location):
return tubport, location return tubport, location
def create_main_tub(basedir, config, tub_options, default_connection_handlers, def create_main_tub(basedir, config, tub_options,
foolscap_connection_handlers, handler_overrides={}): default_connection_handlers, foolscap_connection_handlers,
i2p_provider, tor_provider,
handler_overrides={}, cert_filename="node.pem"):
cfg_tubport = config.get_config("node", "tub.port", None) cfg_tubport = config.get_config("node", "tub.port", None)
cfg_location = config.get_config("node", "tub.location", None) cfg_location = config.get_config("node", "tub.location", None)
portlocation = _tub_portlocation(config, cfg_tubport, cfg_location) portlocation = _tub_portlocation(config, cfg_tubport, cfg_location)
@ -646,9 +646,9 @@ def create_main_tub(basedir, config, tub_options, default_connection_handlers,
# that will create one, so we don't have to stuff all the # that will create one, so we don't have to stuff all the
# options into the tub.port string (which would need a lot # options into the tub.port string (which would need a lot
# of escaping) # of escaping)
port_or_endpoint = self._i2p_provider.get_listener() port_or_endpoint = i2p_provider.get_listener()
elif port == "listen:tor": elif port == "listen:tor":
port_or_endpoint = self._tor_provider.get_listener() port_or_endpoint = tor_provider.get_listener()
else: else:
port_or_endpoint = port port_or_endpoint = port
tub.listenOn(port_or_endpoint) tub.listenOn(port_or_endpoint)
@ -708,7 +708,7 @@ class Node(service.MultiService):
# need them? (note: look in client.py also!) # need them? (note: look in client.py also!)
# (client.py DOES use them in init_client_storage_broker, but # (client.py DOES use them in init_client_storage_broker, but
# we'll want to pull that out as well...so FIXME later) # we'll want to pull that out as well...so FIXME later)
self._default_connection_handlers, self._foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config) ## self._default_connection_handlers, self._foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config)
self.tub = main_tub self.tub = main_tub
if self.tub is not None: if self.tub is not None:

View File

@ -3,6 +3,7 @@ import os
from twisted.python.filepath import FilePath from twisted.python.filepath import FilePath
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import defer
from allmydata.util import yamlutil from allmydata.util import yamlutil
from allmydata.client import create_client from allmydata.client import create_client
from allmydata.scripts.create_node import write_node_config from allmydata.scripts.create_node import write_node_config
@ -33,35 +34,38 @@ class MultiIntroTests(unittest.TestCase):
self.yaml_path = FilePath(os.path.join(self.basedir, "private", self.yaml_path = FilePath(os.path.join(self.basedir, "private",
"introducers.yaml")) "introducers.yaml"))
@defer.inlineCallbacks
def test_introducer_count(self): def test_introducer_count(self):
""" Ensure that the Client creates same number of introducer clients """ Ensure that the Client creates same number of introducer clients
as found in "basedir/private/introducers" config file. """ as found in "basedir/private/introducers" config file. """
connections = {'introducers': connections = {
{ 'introducers': {
u'intro1':{ 'furl': 'furl1' }, u'intro1':{ 'furl': 'furl1' },
u'intro2':{ 'furl': 'furl4' } u'intro2':{ 'furl': 'furl4' },
}, },
} }
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
# get a client and count of introducer_clients # get a client and count of introducer_clients
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
ic_count = len(myclient.introducer_clients) ic_count = len(myclient.introducer_clients)
# assertions # assertions
self.failUnlessEqual(ic_count, 3) self.failUnlessEqual(ic_count, 3)
@defer.inlineCallbacks
def test_introducer_count_commented(self): def test_introducer_count_commented(self):
""" Ensure that the Client creates same number of introducer clients """ Ensure that the Client creates same number of introducer clients
as found in "basedir/private/introducers" config file when there is one as found in "basedir/private/introducers" config file when there is one
commented.""" commented."""
self.yaml_path.setContent(INTRODUCERS_CFG_FURLS_COMMENTED) self.yaml_path.setContent(INTRODUCERS_CFG_FURLS_COMMENTED)
# get a client and count of introducer_clients # get a client and count of introducer_clients
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
ic_count = len(myclient.introducer_clients) ic_count = len(myclient.introducer_clients)
# assertions # assertions
self.failUnlessEqual(ic_count, 2) self.failUnlessEqual(ic_count, 2)
@defer.inlineCallbacks
def test_read_introducer_furl_from_tahoecfg(self): def test_read_introducer_furl_from_tahoecfg(self):
""" Ensure that the Client reads the introducer.furl config item from """ Ensure that the Client reads the introducer.furl config item from
the tahoe.cfg file. """ the tahoe.cfg file. """
@ -78,19 +82,26 @@ class MultiIntroTests(unittest.TestCase):
c.close() c.close()
# get a client and first introducer_furl # get a client and first introducer_furl
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
# assertions # assertions
self.failUnlessEqual(fake_furl, tahoe_cfg_furl) self.failUnlessEqual(fake_furl, tahoe_cfg_furl)
@defer.inlineCallbacks
def test_reject_default_in_yaml(self): def test_reject_default_in_yaml(self):
connections = {'introducers': { connections = {'introducers': {
u'default': { 'furl': 'furl1' }, u'default': { 'furl': 'furl1' },
}} }}
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
e = self.assertRaises(ValueError, create_client, self.basedir) with self.assertRaises(ValueError) as ctx:
self.assertEquals(str(e), "'default' introducer furl cannot be specified in introducers.yaml; please fix impossible configuration.") yield create_client(self.basedir)
self.assertEquals(
str(ctx.exception),
"'default' introducer furl cannot be specified in introducers.yaml; please "
"fix impossible configuration.",
)
SIMPLE_YAML = """ SIMPLE_YAML = """
introducers: introducers:
@ -124,30 +135,38 @@ class NoDefault(unittest.TestCase):
self.yaml_path = FilePath(os.path.join(self.basedir, "private", self.yaml_path = FilePath(os.path.join(self.basedir, "private",
"introducers.yaml")) "introducers.yaml"))
@defer.inlineCallbacks
def test_ok(self): def test_ok(self):
connections = {'introducers': { connections = {'introducers': {
u'one': { 'furl': 'furl1' }, u'one': { 'furl': 'furl1' },
}} }}
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1') self.assertEquals(tahoe_cfg_furl, 'furl1')
@defer.inlineCallbacks
def test_real_yaml(self): def test_real_yaml(self):
self.yaml_path.setContent(SIMPLE_YAML) self.yaml_path.setContent(SIMPLE_YAML)
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1') self.assertEquals(tahoe_cfg_furl, 'furl1')
@defer.inlineCallbacks
def test_invalid_equals_yaml(self): def test_invalid_equals_yaml(self):
self.yaml_path.setContent(EQUALS_YAML) self.yaml_path.setContent(EQUALS_YAML)
e = self.assertRaises(TypeError, create_client, self.basedir) with self.assertRaises(TypeError) as ctx:
self.assertEquals(str(e), "string indices must be integers") yield create_client(self.basedir)
self.assertEquals(
str(ctx.exception),
"string indices must be integers",
)
@defer.inlineCallbacks
def test_introducerless(self): def test_introducerless(self):
connections = {'introducers': {} } connections = {'introducers': {} }
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = create_client(self.basedir) myclient = yield create_client(self.basedir)
self.assertEquals(len(myclient.introducer_furls), 0) self.assertEquals(len(myclient.introducer_furls), 0)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -16,6 +16,10 @@ import foolscap.logging.log
from twisted.application import service from twisted.application import service
from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string, create_node_dir from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string, create_node_dir
from allmydata.node import create_tub
from allmydata.node import create_tub_options
from allmydata.node import create_main_tub
from allmydata.node import create_connection_handlers
from allmydata.introducer.server import create_introducer from allmydata.introducer.server import create_introducer
from allmydata import client from allmydata import client
@ -30,15 +34,26 @@ class LoggingMultiService(service.MultiService):
def log(self, msg, **kw): def log(self, msg, **kw):
pass pass
class TestNode(Node):
CERTFILE='DEFAULT_CERTFILE_BLANK'
def __init__(self, basedir): def testing_tub(config_data=''):
config = read_config( from twisted.internet import reactor
basedir, from allmydata.node import create_i2p_provider, create_tor_provider
'DEFAULT_PORTNUMFILE_BLANK', config = config_from_string(config_data, 'DEFAULT_PORTNUMFILE_BLANK')
) basedir = 'dummy_basedir'
Node.__init__(self, config) fileutil.make_dirs(os.path.join(basedir, 'private'))
i2p_provider = create_i2p_provider(reactor, basedir, config)
tor_provider = create_tor_provider(reactor, basedir, config)
handlers = create_connection_handlers(reactor, basedir, config, i2p_provider, tor_provider)
default_connection_handlers, foolscap_connection_handlers = handlers
tub_options = create_tub_options(config)
main_tub, is_listening = create_main_tub(
basedir, config, tub_options, default_connection_handlers,
foolscap_connection_handlers, i2p_provider, tor_provider,
cert_filename='DEFAULT_CERTFILE_BLANK'
)
return main_tub
class TestCase(testutil.SignalMixin, unittest.TestCase): class TestCase(testutil.SignalMixin, unittest.TestCase):
@ -63,17 +78,21 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
with open(os.path.join(basedir, 'tahoe.cfg'), 'wt') as f: with open(os.path.join(basedir, 'tahoe.cfg'), 'wt') as f:
f.write("[node]\n") f.write("[node]\n")
if tub_port: if tub_port:
f.write("tub.port = %d\n" % (tub_port,)) f.write("tub.port = {}\n".format(tub_port))
if tub_location is not None: if tub_location is not None:
f.write("tub.location = %s\n" % (tub_location,)) f.write("tub.location = {}\n".format(tub_location))
if local_addresses: if local_addresses:
self.patch(iputil, 'get_local_addresses_sync', self.patch(iputil, 'get_local_addresses_sync',
lambda: local_addresses) lambda: local_addresses)
n = TestNode(basedir) tub = testing_tub(config_data)
n.setServiceParent(self.parent) tub.setServiceParent(self.parent)
furl = n.tub.registerReference(n)
class Foo(object):
pass
furl = tub.registerReference(Foo())
for address in expected_addresses: for address in expected_addresses:
self.failUnlessIn(address, furl) self.failUnlessIn(address, furl)
@ -505,10 +524,10 @@ class FakeTub:
def setServiceParent(self, parent): pass def setServiceParent(self, parent): pass
class Listeners(unittest.TestCase): class Listeners(unittest.TestCase):
def test_multiple_ports(self): def test_multiple_ports(self):
basedir = self.mktemp() basedir = self.mktemp()
create_node_dir(basedir, "testing") create_node_dir(basedir, "testing")
port1 = iputil.allocate_tcp_port() port1 = iputil.allocate_tcp_port()
port2 = iputil.allocate_tcp_port() port2 = iputil.allocate_tcp_port()
port = ("tcp:%d:interface=127.0.0.1,tcp:%d:interface=127.0.0.1" % port = ("tcp:%d:interface=127.0.0.1,tcp:%d:interface=127.0.0.1" %
@ -521,20 +540,16 @@ class Listeners(unittest.TestCase):
# we're doing a lot of calling-into-setup-methods here, it might be # we're doing a lot of calling-into-setup-methods here, it might be
# better to just create a real Node instance, I'm not sure. # better to just create a real Node instance, I'm not sure.
config = client.read_config( config = read_config(basedir, "client.port")
basedir,
"client.port", i2p_provider = mock.Mock()
) tor_provider = mock.Mock()
n = Node(config) dfh, fch = create_connection_handlers(None, basedir, config, i2p_provider, tor_provider)
n.check_privacy() tub_options = create_tub_options(config)
n.services = []
n.create_i2p_provider()
n.create_tor_provider()
n.init_connections()
n.set_tub_options()
t = FakeTub() t = FakeTub()
with mock.patch("allmydata.node.Tub", return_value=t): with mock.patch("allmydata.node.Tub", return_value=t):
n.create_main_tub() create_main_tub(basedir, config, tub_options, dfh, fch, i2p_provider, tor_provider)
self.assertEqual(t.listening_ports, self.assertEqual(t.listening_ports,
["tcp:%d:interface=127.0.0.1" % port1, ["tcp:%d:interface=127.0.0.1" % port1,
"tcp:%d:interface=127.0.0.1" % port2]) "tcp:%d:interface=127.0.0.1" % port2])
@ -563,22 +578,25 @@ class Listeners(unittest.TestCase):
i2p_mock = mock.patch('allmydata.node.i2p_provider', new=i2p_x) i2p_mock = mock.patch('allmydata.node.i2p_provider', new=i2p_x)
tor_ep = object() tor_ep = object()
tor_prov = tor_provider.Provider(config, mock.Mock())
tor_prov.get_listener = mock.Mock(return_value=tor_ep)
tor_x = mock.Mock()
tor_x.Provider = lambda c, r: tor_prov
tor_mock = mock.patch('allmydata.node.tor_provider', new=tor_x)
tub_mock = mock.patch("allmydata.node.Tub", return_value=FakeTub()) tor_provider.get_listener = mock.Mock(return_value=tor_ep)
with i2p_mock, tor_mock, tub_mock:
n = Node(config) tub_options = create_tub_options(config)
t = FakeTub()
dfh, fch = create_connection_handlers(None, basedir, config, i2p_provider, tor_provider)
with mock.patch("allmydata.node.Tub", return_value=t):
create_main_tub(basedir, config, tub_options, dfh, fch, i2p_provider, tor_provider)
self.assertEqual(i2p_provider.get_listener.mock_calls, [mock.call()])
self.assertEqual(tor_provider.get_listener.mock_calls, [mock.call()])
self.assertEqual(t.listening_ports, [i2p_ep, tor_ep])
self.assertEqual(n._i2p_provider.get_listener.mock_calls, [mock.call()])
self.assertEqual(n._tor_provider.get_listener.mock_calls, [mock.call()])
self.assertIn(i2p_ep, n.tub.listening_ports)
self.assertIn(tor_ep, n.tub.listening_ports)
class ClientNotListening(unittest.TestCase): class ClientNotListening(unittest.TestCase):
@defer.inlineCallbacks
def test_disabled(self): def test_disabled(self):
basedir = "test_node/test_disabled" basedir = "test_node/test_disabled"
create_node_dir(basedir, "testing") create_node_dir(basedir, "testing")
@ -587,7 +605,7 @@ class ClientNotListening(unittest.TestCase):
f.write(NOLISTEN) f.write(NOLISTEN)
f.write(DISABLE_STORAGE) f.write(DISABLE_STORAGE)
f.close() f.close()
n = client.create_client(basedir) n = yield client.create_client(basedir)
self.assertEqual(n.tub.getListeners(), []) self.assertEqual(n.tub.getListeners(), [])
def test_disabled_but_storage(self): def test_disabled_but_storage(self):